pax_global_header00006660000000000000000000000064125473025530014520gustar00rootroot0000000000000052 comment=75114256d09038d9f3c2463f9021bc7ce9dc1077 elixir-lang-1.1.0~0.20150708/000077500000000000000000000000001254730255300151155ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/.gitattributes000066400000000000000000000000621254730255300200060ustar00rootroot00000000000000lib/elixir/test/elixir/fixtures/*.txt text eol=lf elixir-lang-1.1.0~0.20150708/.gitignore000066400000000000000000000003421254730255300171040ustar00rootroot00000000000000/.eunit /.release /doc /ebin /lib/*/ebin/* /lib/*/tmp /lib/elixir/src/elixir.app.src /lib/elixir/src/*_lexer.erl /lib/elixir/src/*_parser.erl /lib/elixir/test/ebin /rel/elixir erl_crash.dump .elixir.plt man/elixir.1 man/iex.1 elixir-lang-1.1.0~0.20150708/.travis.yml000066400000000000000000000005111254730255300172230ustar00rootroot00000000000000language: erlang otp_release: - 17.0 - 17.3 - 17.4 sudo: false env: - ELIXIR_ERL_OPTIONS="" - ELIXIR_ERL_OPTIONS="+T 9" script: "make compile && rm -rf .git && make test" notifications: irc: "irc.freenode.org#elixir-lang" recipients: - jose.valim@plataformatec.com.br - eric.meadows.jonsson@gmail.com elixir-lang-1.1.0~0.20150708/CHANGELOG.md000066400000000000000000000170651254730255300167370ustar00rootroot00000000000000# Changelog for Elixir v1.1 v1.1 brings enhancements, bug fixes, performance improvements and more into Elixir. Elixir v1.1 supports both Erlang 17 and Erlang 18 and, for this reason, it does not introduce any feature that is specific to Erlang 18. Such will be tackled on the follow up Elixir v1.2 release. On the enhancements side, the most notable changes are the new functions added to `Enum` and `Dict` modules, and a new datatype called `MapSet`. `MapSet` implements the `Set` API on top of a map and, for Elixir v1.1, it is useful for holding only dozens of entries. Future Elixir versions, however, will be able to rely on `MapSet` from dozens of keys up to millions, with better performance than `HashSet`. On the deprecation side, this release includes one major deprecation and some soft deprecations. The major deprecation relates to the Access protocol. Due to performance issues, the access syntax `opts[key]` will no longer be powered by the `Access` protocol, instead, it will use the `Dict` module. Therefore this release will emit warnings if you attempt to implement the `Access` protocol. Note the `Access` module and the `opts[key]` syntax are not affected and they are not deprecated, only the underlying protocol dispatch. The soft deprecations are minor and they won't emit warnings. It simply means the documentation has been updated to mention the new best practices. Warnings will be emitted in the future though (when they are promoted to deprecations). Note: Erlang 17.1 contains a regression in its wildcard implementation that causes tools like rebar to fail. If you have a project with rebar dependencies and is using Erlang 17.1, remember to update to at least Erlang 17.3. ## v1.1.0-dev ### 1 Enhancements * [Application] Add `Application.fetch_env!/2` * [CLI] Add support for `--werl` in Windows bash-like shells * [Dict] Add `Dict.get_and_update/3` which behaves similar to the now deprecated Access protocol * [Dict] Add `Dict.get_lazy/3`, `Dict.pop_lazy/3` and `Dict.put_new_lazy/3` * [EEx] Add `:trim` option to EEx that automatically trims the left side of `<%` and right side `%>` if only spaces and new lines preceed/follow them * [Enum] Add `Enum.random/1`, `Enum.minmax/1`, `Enum.minmax_by/2`, `Enum.reverse_slice/3`, `Enum.dedup/1` and `Enum.dedup_by/2` * [Enum] Inline common map usage in `Enum` functions for performance * [ExUnit] Add number of skipped tests to `ExUnit` output * [ExUnit] Make timeout configurable for the whole test suite via the `:timeout` configuration * [ExUnit] Allow moduledoc to be filtered/skipped in doctests * [File] Add `File.lstat/1` and `File.lstat/1` that works like `File.stat/1` but is able to return symlink information (i.e. it does not traverse symlinks) * [IEx] Add `b/1` helper that shows documentation for behaviour modules and its callback functions * [IEx] Provide tab completion for aliases and allow aliases like `Foo.Bar.Baz` to autocomplete even if `Foo.Bar` is not defined * [Integer] Add `Integer.digits/2` and `Integer.undigits/2` * [Inspect] Add the `:safe` option to `inspect/2` and make it safe by default, meaning failures while inspecting won't trigger other failures. Instead, it will be wrapped in an exception which is properly formatted * [IO] Support fenced code blocks on `IO.ANSI.Docs` * [Kernel] No longer include `:crypto` and `:syntax_tools` as dependencies. The former is only needed if you have encrypted debug info (therefore you can add `:crypto` as a dependency manually) and the latter is no longer used * [Kernel] Raise when `var.Alias` syntax is used and it does not expand to an atom at compile time (previously it just warned) * [Kernel] Improve generation of argument names for function signatures * [Kernel] `::/2` is now a special form * [Logger] Support printing pids and refs in Logger metadata * [Mix] Check Elixir version right after archive installation and provide feedback if there is a mismatch * [Mix] Allow rebar dependencies with `mix.exs` to be compiled with Mix * [Mix] Allow rebar dependencies to be specified via `:path` * [Mix] Also consider subdirectories in `config` directory for `Mix.Project.config_files/0` * [Mix] Allow dynamic configuration in Mix projects by storing config in an agent * [Module] Improve name inference for function signatures in documentation metadata * [Record] Expand attributes and macros when extracting records * [Set] Introduce `MapSet` data type. This new data type uses maps behind the scenes and is useful for storing a dozens of items in Erlang 17. In future versions when maps efficiently support large collections, it is meant to be the main Set abstraction in Elixir * [Stream] Add `Stream.dedup/1` and `Stream.dedup_by/2` * [String] Support calculation of the jaro distance between strings (usually names) via `String.jaro_distance/2`. This is used by Mix to support "Did you mean?" feature when a task does not exist * [String] Add `String.splitter/3` that splits strings as a stream * [StringIO] `StringIO.flush/1` was added to flush the output of a StringIO device * [URI] Default ports were added for "ws" and "wss" schemas ### 2. Bug fixes * [Code] `:delegate_locals_to` failed to delegate to the chosen module in many situations and messed up stacktraces. This option has therefore been replaced by imports * [EEx] Allow EEx interpolation to also apply inside quotations `<%%= ... %>` * [Exception] Do not fail when calculating an exception message, even if the message is invalid * [ExUnit] Skipped tests now correctly count towards the total of tests in the result returned by `ExUnit.run/0` * [ExUnit] Fix a bug where failures when inspecting data structure or retrieving error messages could bring the whole ExUnit runner down * [ExUnit] Ensure the Logger is flushed when running ExUnit via Mix * [Kernel] Do not expand `in/2` argument in module body * [Kernel] Throw syntax error for undefind atom/alias syntax `:foo.Bar` * [Kernel] Improve error message when we can't compile because the target directory is not writeable * [Mix] Ensure automatic protocol consolidation via `:consolidate_protocols` is triggered in umbrella apps * [Mix] Do not raise if wildcard given to `import_config` does not match any file * [Mix] Applications with build_embedded set to true require explicit compilation step * [Module] Do not accept non-Elixir module names in `Module.split/1` * [Protocol] Guarantee that derived protocols go through `Any` instead of `Map` * [Regex] Fix splitting of empty strings with regexes when trim is set to `true`. Now both `String.split/3` and `Regex.split/3` return an empty list when called with an empty string and trim is enabled * [Regex] Fix `Regex.replace/4` so it doesn't discard escape characters ### 3. Soft deprecations (no warnings emitted) * [Enum] `Enum.uniq/2` is deprecated in favor of `Enum.uniq_by/2` * [Regex] Ungreedy option `r` is deprecated in favor of `U` (which is standard in regular expressions in other languages) ### 4. Deprecations * [Access] Implementing the Access protocol is deprecated. The Access protocol relies on the code server in development and test mode (when protocol consolidation is not applied) and it generated a bottleneck when working with multiple processes and the Access protocol was invoked hundreds of times (which is not uncommon). Note the `Access` module and the `opts[key]` syntax are not affected and they are not deprecated, only the underlying protocol dispatch * [String] Passing an empty string to `starts_with?` and `ends_with?` had dubious behaviour and have been deprecated to help developers identify possible bugs in their source code elixir-lang-1.1.0~0.20150708/CONTRIBUTING.md000066400000000000000000000214141254730255300173500ustar00rootroot00000000000000# Contributing to Elixir Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved! ## Using the issue tracker Use the issues tracker for: * [bug reports](#bug-reports) * [submitting pull requests](#pull-requests) Please **do not** use the issue tracker for personal support requests nor feature requests. Support requests should be sent to: * [the elixir-talk mailing list](http://groups.google.com/group/elixir-lang-talk) * [Stack Overflow](http://stackoverflow.com/questions/ask?tags=elixir) * **[#elixir-lang](irc://chat.freenode.net/elixir-lang)** IRC channel on [chat.freenode.net](http://www.freenode.net/) Feature requests can be discussed on [the elixir-core mailing list](http://groups.google.com/group/elixir-lang-core). We do our best to keep the issue tracker tidy and organized, making it useful for everyone. For example, we classify open issues per application and perceived difficulty of the issue, making it easier for developers to [contribute to Elixir](#contributing). ## Bug reports A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you! Guidelines for bug reports: 1. **Use the GitHub issue search** — check if the issue has already been reported. 2. **Check if the issue has been fixed** — try to reproduce it using the `master` branch in the repository. 3. **Isolate and report the problem** — ideally create a reduced test case. Please try to be as detailed as possible in your report. Include information about your Operating System, your Erlang and Elixir versions. Please provide steps to reproduce the issue as well as the outcome you were expecting! All these details will help developers to fix any potential bugs. Example: > Short and descriptive example bug report title > > A summary of the issue and the environment in which it occurs. If suitable, > include the steps required to reproduce the bug. > > 1. This is the first step > 2. This is the second step > 3. Further steps, etc. > > `` - a link to the reduced test case (e.g. a GitHub Gist) > > Any other information you want to share that is relevant to the issue being > reported. This might include the lines of code that you have identified as > causing the bug, and potential solutions (and your opinions on their > merits). ## Feature requests Feature requests are welcome and should be discussed on [the elixir-core mailing list](http://groups.google.com/group/elixir-lang-core). But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to *you* to make a strong case to convince the community of the merits of this feature. Please provide as much detail and context as possible. ## Contributing We incentivize everyone to contribute to Elixir and help us tackle existing issues! To do so, there are a few things you need to know about the code. First, Elixir code is divided in applications inside the `lib` folder: * `elixir` - Contains Elixir's kernel and stdlib * `eex` - Template engine that allows you to embed Elixir * `ex_unit` - Simple test framework that ships with Elixir * `iex` — IEx, Elixir's interactive shell * `mix` — Elixir's build tool You can run all tests in the root directory with `make test` and you can also run tests for a specific framework `make test_#{NAME}`, for example, `make test_ex_unit`. In case you are changing a single file, you can compile and run tests only for that particular file for fast development cycles. For example, if you are changing the String module, you can compile it and run its tests as: $ bin/elixirc lib/elixir/lib/string.ex -o lib/elixir/ebin $ bin/elixir lib/elixir/test/elixir/string_test.exs After your changes are done, please remember to run the full suite with `make test`. From time to time, your tests may fail in an existing Elixir checkout and may require a clean start by running `make clean compile`. You can always check [the official build status on Travis-CI](https://travis-ci.org/elixir-lang/elixir). With tests running and passing, you are ready to contribute to Elixir and send your pull requests. ## Contributing Documentation Code documentation (`@doc`, `@moduledoc`, `@typedoc`) has a special convention: the first paragraph is considered to be a short summary. For functions, macros and callbacks say what it will do. For example write something like: ```elixir @doc """ Returns only those elements for which `fun` is `true`. ... """ def filter(collection, fun) ... ``` For modules, protocols and types say what it is. For example write something like: ```elixir defmodule File.Stat do @moduledoc """ Information about a file. ... """ defstruct [...] end ``` Keep in mind that the first paragraph might show up in a summary somewhere, long texts in the first paragraph create very ugly summaries. As a rule of thumb anything longer than 80 characters is too long. Try to keep unnecessary details out of the first paragraph, it's only there to give a user a quick idea of what the documented "thing" does/is. The rest of the documentation string can contain the details, for example when a value and when `nil` is returned. If possible include examples, preferably in a form that works with doctests. For example: ```elixir @doc """ Return only those elements for which `fun` is `true`. ## Examples iex> Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) [2] """ def filter(collection, fun) ... ``` This makes it easy to test the examples so that they don't go stale and examples are often a great help in explaining what a function does. ## Pull requests Good pull requests - patches, improvements, new features - are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. **IMPORTANT**: By submitting a patch, you agree that your work will be licensed under the license used by the project. If you have any large pull request in mind (e.g. implementing features, refactoring code, etc), **please ask first** otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project. Please adhere to the coding conventions in the project (indentation, accurate comments, etc.) and don't forget to add your own tests and documentation. When working with git, we recommend the following process in order to craft an excellent pull request: 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes: ```bash # Clone your fork of the repo into the current directory git clone https://github.com//elixir # Navigate to the newly cloned directory cd elixir # Assign the original repo to a remote called "upstream" git remote add upstream https://github.com/elixir-lang/elixir ``` 2. If you cloned a while ago, get the latest changes from upstream: ```bash git checkout master git pull upstream master ``` 3. Create a new topic branch (off of `master`) to contain your feature, change, or fix. **IMPORTANT**: Making changes in `master` is discouraged. You should always keep your local `master` in sync with upstream `master` and make your changes in topic branches. ```bash git checkout -b ``` 4. Commit your changes in logical chunks. Keep your commit messages organized, with a short description in the first line and more detailed information on the following lines. Feel free to use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public. 5. Make sure all the tests are still passing. ```bash make test ``` This command will compile the code in your branch and use that version of Elixir to run the tests. This is needed to ensure your changes can pass all the tests. 6. Push your topic branch up to your fork: ```bash git push origin ``` 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description. 8. If you haven't updated your pull request for a while, you should consider rebasing on master and resolving any conflicts. **IMPORTANT**: _Never ever_ merge upstream `master` into your branches. You should always `git rebase` on `master` to bring your changes up to date when necessary. ```bash git checkout master git pull upstream master git checkout git rebase master ``` We have saved some excellent pull requests we have received in the past in case you are looking for some examples: * https://github.com/elixir-lang/elixir/pull/992 * https://github.com/elixir-lang/elixir/pull/1058 * https://github.com/elixir-lang/elixir/pull/1059 Thank you for your contributions! elixir-lang-1.1.0~0.20150708/LEGAL000066400000000000000000000004651254730255300156710ustar00rootroot00000000000000LEGAL NOTICE INFORMATION ------------------------ All the files in this distribution are covered under either Elixir's license (see the file LICENSE) except the files mentioned below that contains sections that are under Erlang's License (EPL): lib/elixir/src/elixir_parser.erl (generated by build scripts) elixir-lang-1.1.0~0.20150708/LICENSE000066400000000000000000000010731254730255300161230ustar00rootroot00000000000000Copyright 2012 Plataformatec Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.elixir-lang-1.1.0~0.20150708/Makefile000066400000000000000000000210631254730255300165570ustar00rootroot00000000000000REBAR ?= $(CURDIR)/rebar PREFIX ?= /usr/local DOCS := master ELIXIRC := bin/elixirc --verbose --ignore-module-conflict ERLC := erlc -I lib/elixir/include ERL := erl -I lib/elixir/include -noshell -pa lib/elixir/ebin VERSION := $(strip $(shell cat VERSION)) Q := @ LIBDIR := lib INSTALL = install INSTALL_DIR = $(INSTALL) -m755 -d INSTALL_DATA = $(INSTALL) -m644 INSTALL_PROGRAM = $(INSTALL) -m755 .PHONY: install install_man compile erlang elixir build_plt clean_plt dialyze test clean docs release_docs release_zip check_erlang_release .NOTPARALLEL: compile #==> Functions # This check should work for older versions like R16B # as well as new verions like 17.1 and 18 define CHECK_ERLANG_RELEASE $(Q) erl -noshell -eval 'io:fwrite("~s", [erlang:system_info(otp_release)])' -s erlang halt | grep -q '^1[789]'; \ if [ $$? != 0 ]; then \ echo "At least Erlang 17.0 is required to build Elixir"; \ exit 1; \ fi; endef define APP_TEMPLATE $(1): lib/$(1)/ebin/Elixir.$(2).beam lib/$(1)/ebin/$(1).app lib/$(1)/ebin/$(1).app: lib/$(1)/mix.exs $(Q) mkdir -p lib/$(1)/_build/shared/lib/$(1) $(Q) cp -R lib/$(1)/ebin lib/$(1)/_build/shared/lib/$(1)/ $(Q) cd lib/$(1) && ../../bin/elixir -e 'Mix.start(:permanent, [])' -r mix.exs -e 'Mix.Task.run("compile.app")' $(Q) cp lib/$(1)/_build/shared/lib/$(1)/ebin/$(1).app lib/$(1)/ebin/$(1).app $(Q) rm -rf lib/$(1)/_build lib/$(1)/ebin/Elixir.$(2).beam: $(wildcard lib/$(1)/lib/*.ex) $(wildcard lib/$(1)/lib/*/*.ex) $(wildcard lib/$(1)/lib/*/*/*.ex) @ echo "==> $(1) (compile)" @ rm -rf lib/$(1)/ebin $(Q) cd lib/$(1) && ../../$$(ELIXIRC) "lib/**/*.ex" -o ebin test_$(1): $(1) @ echo "==> $(1) (exunit)" $(Q) cd lib/$(1) && ../../bin/elixir -r "test/test_helper.exs" -pr "test/**/*_test.exs"; endef #==> Compilation tasks KERNEL:=lib/elixir/ebin/Elixir.Kernel.beam UNICODE:=lib/elixir/ebin/Elixir.String.Unicode.beam default: compile compile: lib/elixir/src/elixir.app.src erlang elixir lib/elixir/src/elixir.app.src: src/elixir.app.src $(Q) $(call CHECK_ERLANG_RELEASE) $(Q) rm -rf lib/elixir/src/elixir.app.src $(Q) echo "%% This file is automatically generated from /src/elixir.app.src" \ >lib/elixir/src/elixir.app.src $(Q) cat src/elixir.app.src >>lib/elixir/src/elixir.app.src erlang: $(Q) cd lib/elixir && $(REBAR) compile # Since Mix depends on EEx and EEx depends on # Mix, we first compile EEx without the .app # file, then mix and then compile EEx fully elixir: stdlib lib/eex/ebin/Elixir.EEx.beam mix ex_unit logger eex iex stdlib: $(KERNEL) VERSION $(KERNEL): lib/elixir/lib/*.ex lib/elixir/lib/*/*.ex lib/elixir/lib/*/*/*.ex $(Q) if [ ! -f $(KERNEL) ]; then \ echo "==> bootstrap (compile)"; \ $(ERL) -s elixir_compiler core -s erlang halt; \ fi @ echo "==> elixir (compile)"; $(Q) cd lib/elixir && ../../$(ELIXIRC) "lib/kernel.ex" -o ebin; $(Q) cd lib/elixir && ../../$(ELIXIRC) "lib/**/*.ex" -o ebin; $(Q) $(MAKE) unicode $(Q) rm -rf lib/elixir/ebin/elixir.app $(Q) cd lib/elixir && $(REBAR) compile unicode: $(UNICODE) $(UNICODE): lib/elixir/unicode/* @ echo "==> unicode (compile)"; @ echo "Embedding the Unicode database... (this may take a while)" $(Q) cd lib/elixir && ../../$(ELIXIRC) unicode/unicode.ex -o ebin; $(eval $(call APP_TEMPLATE,ex_unit,ExUnit)) $(eval $(call APP_TEMPLATE,logger,Logger)) $(eval $(call APP_TEMPLATE,eex,EEx)) $(eval $(call APP_TEMPLATE,mix,Mix)) $(eval $(call APP_TEMPLATE,iex,IEx)) install: compile @ echo "==> elixir (install)" $(Q) for dir in lib/*; do \ rm -Rf $(DESTDIR)$(PREFIX)/$(LIBDIR)/elixir/$$dir/ebin; \ $(INSTALL_DIR) "$(DESTDIR)$(PREFIX)/$(LIBDIR)/elixir/$$dir/ebin"; \ $(INSTALL_DATA) $$dir/ebin/* "$(DESTDIR)$(PREFIX)/$(LIBDIR)/elixir/$$dir/ebin"; \ done $(Q) $(INSTALL_DIR) "$(DESTDIR)$(PREFIX)/$(LIBDIR)/elixir/bin" $(Q) $(INSTALL_PROGRAM) $(filter-out %.ps1, $(filter-out %.bat, $(wildcard bin/*))) "$(DESTDIR)$(PREFIX)/$(LIBDIR)/elixir/bin" $(Q) $(INSTALL_DIR) "$(DESTDIR)$(PREFIX)/bin" $(Q) for file in "$(DESTDIR)$(PREFIX)"/$(LIBDIR)/elixir/bin/* ; do \ ln -sf "../$(LIBDIR)/elixir/bin/$${file##*/}" "$(DESTDIR)$(PREFIX)/bin/" ; \ done $(MAKE) install_man install_man: $(Q) mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1 cd man && $(MAKE) build $(Q) $(INSTALL_DATA) man/elixir.1 $(DESTDIR)$(PREFIX)/share/man/man1 $(Q) $(INSTALL_DATA) man/elixirc.1 $(DESTDIR)$(PREFIX)/share/man/man1 $(Q) $(INSTALL_DATA) man/iex.1 $(DESTDIR)$(PREFIX)/share/man/man1 $(Q) $(INSTALL_DATA) man/mix.1 $(DESTDIR)$(PREFIX)/share/man/man1 clean: cd lib/elixir && $(REBAR) clean rm -rf ebin rm -rf lib/*/ebin rm -rf lib/elixir/test/ebin rm -rf lib/*/tmp rm -rf lib/mix/test/fixtures/git_repo rm -rf lib/mix/test/fixtures/deps_on_git_repo rm -rf lib/mix/test/fixtures/git_rebar rm -rf lib/elixir/src/elixir.app.src cd man && $(MAKE) clean clean_exbeam: $(Q) rm -f lib/*/ebin/Elixir.*.beam #==> Create Documentation SOURCE_REF = $(shell head="$$(git rev-parse HEAD)" tag="$$(git tag --points-at $$head | tail -1)" ; echo "$${tag:-$$head}\c") COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" -m "$(3)" -u "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" -o doc/$(2) -p http://elixir-lang.org/docs.html docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger docs_elixir: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (elixir)" $(Q) rm -rf doc/elixir $(call COMPILE_DOCS,Elixir,elixir,Kernel) docs_eex: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (eex)" $(Q) rm -rf doc/eex $(call COMPILE_DOCS,EEx,eex,EEx) docs_mix: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (mix)" $(Q) rm -rf doc/mix $(call COMPILE_DOCS,Mix,mix,Mix) docs_iex: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (iex)" $(Q) rm -rf doc/iex $(call COMPILE_DOCS,IEx,iex,IEx) docs_ex_unit: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (ex_unit)" $(Q) rm -rf doc/ex_unit $(call COMPILE_DOCS,ExUnit,ex_unit,ExUnit) docs_logger: compile ../ex_doc/bin/ex_doc @ echo "==> ex_doc (logger)" $(Q) rm -rf doc/logger $(call COMPILE_DOCS,Logger,logger,Logger) ../ex_doc/bin/ex_doc: @ echo "ex_doc is not found in ../ex_doc as expected. See README for more information." @ false #==> Release tasks release_zip: compile rm -rf v$(VERSION).zip zip -9 -r v$(VERSION).zip bin CHANGELOG.md LEGAL lib/*/ebin LICENSE Makefile README.md VERSION release_docs: docs rm -rf ../docs/$(DOCS)/*/ mv doc/* ../docs/$(DOCS) # This task requires aws-cli to be installed and set up for access to s3.hex.pm # See: http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html publish_mix: compile cd lib/mix && MIX_ENV=prod mix escript.build aws s3 cp lib/mix/mix s3://s3.hex.pm/builds/mix/v$(VERSION)/mix --acl public-read aws s3 cp lib/mix/mix s3://s3.hex.pm/builds/mix/mix --acl public-read rm lib/mix/mix rm -rf lib/mix/_build #==> Tests tasks test: test_erlang test_elixir TEST_ERL = lib/elixir/test/erlang TEST_EBIN = lib/elixir/test/ebin TEST_ERLS = $(addprefix $(TEST_EBIN)/, $(addsuffix .beam, $(basename $(notdir $(wildcard $(TEST_ERL)/*.erl))))) test_erlang: compile $(TEST_ERLS) @ echo "==> elixir (eunit)" $(Q) $(ERL) -pa $(TEST_EBIN) -s test_helper test; @ echo "" $(TEST_EBIN)/%.beam: $(TEST_ERL)/%.erl $(Q) mkdir -p $(TEST_EBIN) $(Q) $(ERLC) -o $(TEST_EBIN) $< test_elixir: test_stdlib test_ex_unit test_logger test_doc_test test_mix test_eex test_iex test_doc_test: compile @ echo "==> doctest (exunit)" $(Q) cd lib/elixir && ../../bin/elixir -r "test/doc_test.exs"; test_stdlib: compile @ echo "==> elixir (exunit)" $(Q) exec epmd & exit $(Q) if [ "$(OS)" = "Windows_NT" ]; then \ cd lib/elixir && cmd //C call ../../bin/elixir.bat -r "test/elixir/test_helper.exs" -pr "test/elixir/**/*_test.exs"; \ else \ cd lib/elixir && ../../bin/elixir -r "test/elixir/test_helper.exs" -pr "test/elixir/**/*_test.exs"; \ fi #==> Dialyzer tasks DIALYZER_OPTS = --no_check_plt --fullpath -Werror_handling -Wunmatched_returns -Wunderspecs PLT = .elixir.plt $(PLT): @ echo "==> Building PLT with Elixir's dependencies..." $(Q) dialyzer --output_plt $(PLT) --build_plt --apps erts kernel stdlib compiler syntax_tools parsetools tools ssl inets clean_plt: $(Q) rm -f $(PLT) build_plt: clean_plt $(PLT) dialyze: compile $(PLT) @ echo "==> Dialyzing Elixir..." $(Q) dialyzer --plt $(PLT) $(DIALYZER_OPTS) lib/*/ebin elixir-lang-1.1.0~0.20150708/README.md000066400000000000000000000054641254730255300164050ustar00rootroot00000000000000![Elixir](https://github.com/elixir-lang/elixir-lang.github.com/raw/master/images/logo/logo.png) ========= [![Build Status](https://secure.travis-ci.org/elixir-lang/elixir.svg?branch=master "Build Status")](http://travis-ci.org/elixir-lang/elixir) For more about Elixir, installation and documentation, [check Elixir's website](http://elixir-lang.org/). ## Usage If you want to contribute to Elixir or run it from source, clone this repository to your machine, compile and test it: $ git clone https://github.com/elixir-lang/elixir.git $ cd elixir $ make clean test > Note: if you are running on Windows, [this article includes important notes for compiling Elixir from source on Windows](https://github.com/elixir-lang/elixir/wiki/Windows). If Elixir fails to build (specifically when pulling in a new version via git), be sure to remove any previous build artifacts by running `make clean`, then `make test`. If tests pass, you are ready to move on to the [Getting Started guide][1] or to try Interactive Elixir by running: `bin/iex` in your terminal. However, if tests fail, it is likely you have an outdated Erlang version (Elixir requires Erlang 17.0 or later). You can check your Erlang version by calling `erl` in the command line. You will see some information as follows: Erlang/OTP 17 [erts-6.0] [source-07b8f44] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] If you have the correct version and tests still fail, feel free to [open an issue][2]. ## Building documentation Building the documentation requires [ex_doc](https://github.com/elixir-lang/ex_doc) to be installed and built in the same containing folder as elixir. # After cloning and compiling Elixir $ git clone git://github.com/elixir-lang/ex_doc.git $ cd ex_doc && ../elixir/bin/mix do deps.get, compile $ cd ../elixir && make docs ## Contributing We appreciate any contribution to Elixir, so check out our [CONTRIBUTING.md](CONTRIBUTING.md) guide for more information. We usually keep a list of features and bugs [in the issue tracker][2]. ## Important links * [Elixir Website][1] * [Elixir Documentation][7] * **[#elixir-lang][5]** on [Freenode][6] IRC * [Issue tracker][2] * [elixir-talk Mailing list (questions)][3] * [elixir-core Mailing list (development)][4] [1]: http://elixir-lang.org [2]: https://github.com/elixir-lang/elixir/issues [3]: http://groups.google.com/group/elixir-lang-talk [4]: http://groups.google.com/group/elixir-lang-core [5]: irc://chat.freenode.net/elixir-lang [6]: http://www.freenode.net/ [7]: http://elixir-lang.org/docs.html ## License "Elixir" and the Elixir logo are copyright (c) 2012 Plataformatec. Elixir source code is released under Apache 2 License with some parts under Erlang's license (EPL). Check [LEGAL](LEGAL) and [LICENSE](LICENSE) files for more information. elixir-lang-1.1.0~0.20150708/RELEASE.md000066400000000000000000000025431254730255300165230ustar00rootroot00000000000000# Release process ## All releases This document simply outlines the release process: 1. Ensure you are running on the oldest supported Erlang version 2. Remove all `-dev` extension from versions (see below for all files) 3. Ensure CHANGELOG is updated and add current date 4. Commit changes above with title "Release vVERSION" and generate new tag 5. Run `make clean test` to ensure all tests pass from scratch and the CI is green 6. Ensure minimum supported Hex works with new release (instructions upcoming) 7. Push branch and the new tag 8. Release new docs with `make release_docs`, copy docs to `docs/stable` if appropriate, and push 9. Release new zip with `make release_zip`, push `Precompiled.zip` to GitHub Releases 10. Add the release to `elixir.csv` file in `elixir-lang/elixir-lang.github.com` 11. Build and push standalone Mix with `make publish_mix` (requires AWS credentials) ## New vMAJOR.MINOR releases 12. Create a new branch "vMAJOR.MINOR" 13. Move docs generation to `docs/vMAJOR.MINOR` and copy them from `docs/stable` 14. In master, bump versions, start new CHANGELOG, add `-dev` back and commit "Start vVERSION+1" 15. `make release_docs` and push it to `elixir-lang/docs` ## Places where version is mentioned * VERSION (make sure there is no newline in this file) * CHANGELOG.md * src/elixir.app.src (not lib/elixir/src/elixir.app.src) elixir-lang-1.1.0~0.20150708/VERSION000066400000000000000000000000111254730255300161550ustar00rootroot000000000000001.1.0-develixir-lang-1.1.0~0.20150708/bin/000077500000000000000000000000001254730255300156655ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/bin/elixir000077500000000000000000000060351254730255300171130ustar00rootroot00000000000000#!/bin/sh if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then echo "Usage: `basename $0` [options] [.exs file] [data] -v Prints version and exit -e \"command\" Evaluates the given command (*) -r \"file\" Requires the given files/patterns (*) -S \"script\"   Finds and executes the given script -pr \"file\" Requires the given files/patterns in parallel (*) -pa \"path\" Prepends the given path to Erlang code path (*) -pz \"path\" Appends the given path to Erlang code path (*) --app \"app\" Start the given app and its dependencies (*) --erl \"switches\" Switches to be passed down to erlang (*) --name \"name\" Makes and assigns a name to the distributed node --sname \"name\" Makes and assigns a short name to the distributed node --cookie \"cookie\" Sets a cookie for this distributed node --hidden Makes a hidden node --detached Starts the Erlang VM detached from console --werl Uses Erlang's Windows shell GUI (Windows only) --no-halt Does not halt the Erlang VM after execution ** Options marked with (*) can be given more than once ** Options given after the .exs file or -- are passed down to the executed code ** Options can be passed to the erlang runtime using ELIXIR_ERL_OPTIONS or --erl" >&2 exit 1 fi readlink_f () { cd "$(dirname "$1")" > /dev/null filename="$(basename "$1")" if [ -h "$filename" ]; then readlink_f "$(readlink "$filename")" else echo "`pwd -P`/$filename" fi } MODE="elixir" ERL_EXEC="erl" ERL="" I=1 while [ $I -le $# ]; do S=1 eval "PEEK=\${$I}" case "$PEEK" in +iex) MODE="iex" ;; +elixirc) MODE="elixirc" ;; -v|--compile|--no-halt) ;; -e|-r|-pr|-pa|-pz|--remsh|--app) S=2 ;; --detached|--hidden) ERL="$ERL `echo $PEEK | cut -c 2-`" ;; --cookie) I=$(expr $I + 1) eval "VAL=\${$I}" ERL="$ERL -setcookie "$VAL"" ;; --sname|--name) I=$(expr $I + 1) eval "VAL=\${$I}" ERL="$ERL `echo $PEEK | cut -c 2-` "$VAL"" ;; --erl) I=$(expr $I + 1) eval "VAL=\${$I}" ERL="$ERL "$VAL"" ;; --werl) USE_WERL=true ;; *) break ;; esac I=$(expr $I + $S) done SELF=$(readlink_f "$0") SCRIPT_PATH=$(dirname "$SELF") if [ "$OSTYPE" = "cygwin" ]; then SCRIPT_PATH=$(cygpath -m "$SCRIPT_PATH"); fi if [ "$MODE" != "iex" ]; then ERL="-noshell -s elixir start_cli $ERL"; fi # Check for terminal support if [ "$OS" != "Windows_NT" ]; then if test -t 1 -a -t 2; then ERL="-elixir ansi_enabled true $ERL"; fi fi if [ "$OS" = "Windows_NT" ] && [ $USE_WERL ]; then ERL_EXEC="werl" fi if [ -z "$ERL_PATH" ]; then if [ -f "$SCRIPT_PATH/../releases/RELEASES" ] && [ -f "$SCRIPT_PATH/erl" ]; then ERL_PATH="$SCRIPT_PATH"/"$ERL_EXEC" else ERL_PATH="$ERL_EXEC" fi fi exec "$ERL_PATH" -pa "$SCRIPT_PATH"/../lib/*/ebin $ELIXIR_ERL_OPTIONS $ERL -extra "$@" elixir-lang-1.1.0~0.20150708/bin/elixir.bat000066400000000000000000000075771254730255300176710ustar00rootroot00000000000000@echo off setlocal if "%1"=="" goto documentation if "%1"=="--help" goto documentation if "%1"=="-h" goto documentation if "%1"=="/h" goto documentation goto parseopts :documentation echo Usage: %~nx0 [options] [.exs file] [data] echo. echo -v Prints version and exit echo -e command Evaluates the given command (*) echo -r file Requires the given files/patterns (*) echo -S script Finds and executes the given script echo -pr file Requires the given files/patterns in parallel (*) echo -pa path Prepends the given path to Erlang code path (*) echo -pz path Appends the given path to Erlang code path (*) echo --app app Start the given app and its dependencies (*) echo --erl switches Switches to be passed down to erlang (*) echo --name name Makes and assigns a name to the distributed node echo --sname name Makes and assigns a short name to the distributed node echo --cookie cookie Sets a cookie for this distributed node echo --hidden Makes a hidden node echo --detached Starts the Erlang VM detached from console echo --werl Uses Erlang's Windows shell GUI echo --no-halt Does not halt the Erlang VM after execution echo. echo ** Options marked with (*) can be given more than once echo ** Options given after the .exs file or -- are passed down to the executed code echo ** Options can be passed to the erlang runtime using ELIXIR_ERL_OPTIONS or --erl goto end :parseopts rem Parameters for Erlang set parsErlang= rem Make sure we keep a copy of all parameters set allPars=%* rem Get the original path name from the batch file set originPath=%~dp0 rem Optional parameters before the "-extra" parameter set beforeExtra= rem Flag which determines whether or not to use werl vs erl set useWerl=0 rem Designates which mode / Elixir component to run as set runMode="elixir" rem Recursive loop called for each parameter that parses the cmd line parameters :startloop set par="%1" shift if "%par%"=="" ( rem if no parameters defined goto :expand_erl_libs ) if "%par%"=="""" ( rem if no parameters defined - special case for parameter that is already quoted goto :expand_erl_libs ) rem ******* EXECUTION OPTIONS ********************** IF "%par%"==""--werl"" (Set useWerl=1) IF "%par%"==""+iex"" (Set runMode="iex") rem ******* elixir parameters ********************** rem Note: we don't have to do anything with options that don't take an argument IF """"=="%par:-e=%" (shift) IF """"=="%par:-r=%" (shift) IF """"=="%par:-pr=%" (shift) IF """"=="%par:-pa=%" (shift) IF """"=="%par:-pz=%" (shift) IF """"=="%par:--app=%" (shift) IF """"=="%par:--remsh=%" (shift) rem ******* ERLANG PARAMETERS ********************** IF """"=="%par:--detached=%" (Set parsErlang=%parsErlang% -detached) IF """"=="%par:--hidden=%" (Set parsErlang=%parsErlang% -hidden) IF """"=="%par:--cookie=%" (Set parsErlang=%parsErlang% -setcookie %1 && shift) IF """"=="%par:--sname=%" (Set parsErlang=%parsErlang% -sname %1 && shift) IF """"=="%par:--name=%" (Set parsErlang=%parsErlang% -name %1 && shift) IF """"=="%par:--erl=%" (Set beforeExtra=%beforeExtra% %~1 && shift) goto:startloop rem ******* assume all pre-params are parsed ******************** :expand_erl_libs rem ******* expand all ebin paths as Windows does not support the ..\*\ebin wildcard ******************** SETLOCAL enabledelayedexpansion set ext_libs= for /d %%d in ("%originPath%..\lib\*.") do ( set ext_libs=!ext_libs! -pa "%%~fd\ebin" ) SETLOCAL disabledelayedexpansion :run IF NOT %runMode% == "iex" ( set beforeExtra=-noshell -s elixir start_cli %beforeExtra% ) IF %useWerl% EQU 1 ( start werl.exe %ext_libs% %ELIXIR_ERL_OPTIONS% %parsErlang% %beforeExtra% -extra %* ) ELSE ( erl.exe %ext_libs% %ELIXIR_ERL_OPTIONS% %parsErlang% %beforeExtra% -extra %* ) :end endlocal elixir-lang-1.1.0~0.20150708/bin/elixirc000077500000000000000000000017731254730255300172620ustar00rootroot00000000000000#!/bin/sh if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then echo "Usage: `basename $0` [elixir switches] [compiler switches] [.ex files] -o The directory to output compiled files --no-docs Do not attach documentation to compiled modules --no-debug-info Do not attach debug info to compiled modules --ignore-module-conflict --warnings-as-errors Treat warnings as errors and return non-zero exit code --verbose Print informational messages. ** Options given after -- are passed down to the executed code ** Options can be passed to the erlang runtime using ELIXIR_ERL_OPTIONS ** Options can be passed to the erlang compiler using ERL_COMPILER_OPTIONS" >&2 exit 1 fi readlink_f () { cd "$(dirname "$1")" > /dev/null filename="$(basename "$1")" if [ -h "$filename" ]; then readlink_f "$(readlink "$filename")" else echo "`pwd -P`/$filename" fi } SELF=$(readlink_f "$0") SCRIPT_PATH=$(dirname "$SELF") exec "$SCRIPT_PATH"/elixir +elixirc "$@" elixir-lang-1.1.0~0.20150708/bin/elixirc.bat000066400000000000000000000017031254730255300200150ustar00rootroot00000000000000@echo off set argc=0 for %%A in (%*) do ( if "%%A"=="--help" goto documentation if "%%A"=="-h" goto documentation if "%%A"=="/h" goto documentation set /A argc+=1 ) if %argc%==0 goto documentation goto run :documentation echo Usage: %~nx0 [elixir switches] [compiler switches] [.ex files] echo. echo -o The directory to output compiled files echo --no-docs Do not attach documentation to compiled modules echo --no-debug-info Do not attach debug info to compiled modules echo --ignore-module-conflict echo --warnings-as-errors Treat warnings as errors and return non-zero exit code echo --verbose Print informational messages. echo. echo ** Options given after -- are passed down to the executed code echo ** Options can be passed to the erlang runtime using ELIXIR_ERL_OPTIONS echo ** Options can be passed to the erlang compiler using ERL_COMPILER_OPTIONS >&2 :run call "%~dp0\elixir.bat" +elixirc %* elixir-lang-1.1.0~0.20150708/bin/iex000077500000000000000000000034351254730255300164050ustar00rootroot00000000000000#!/bin/sh if [ $# -gt 0 ] && ([ "$1" = "--help" ] || [ "$1" = "-h" ]); then echo "Usage: `basename $0` [options] [.exs file] [data] -v Prints version -e \"command\" Evaluates the given command (*) -r \"file\" Requires the given files/patterns (*) -S \"script\"   Finds and executes the given script -pr \"file\" Requires the given files/patterns in parallel (*) -pa \"path\" Prepends the given path to Erlang code path (*) -pz \"path\" Appends the given path to Erlang code path (*) --app \"app\" Start the given app and its dependencies (*) --erl \"switches\" Switches to be passed down to erlang (*) --name \"name\" Makes and assigns a name to the distributed node --sname \"name\" Makes and assigns a short name to the distributed node --cookie \"cookie\" Sets a cookie for this distributed node --hidden Makes a hidden node --werl Uses Erlang's Windows shell GUI (Windows only) --detached Starts the Erlang VM detached from console --remsh \"name\" Connects to a node using a remote shell --dot-iex \"path\" Overrides default .iex.exs file and uses path instead; path can be empty, then no file will be loaded ** Options marked with (*) can be given more than once ** Options given after the .exs file or -- are passed down to the executed code ** Options can be passed to the VM using ELIXIR_ERL_OPTIONS or --erl" >&2 exit 1 fi readlink_f () { cd "$(dirname "$1")" > /dev/null filename="$(basename "$1")" if [ -h "$filename" ]; then readlink_f "$(readlink "$filename")" else echo "`pwd -P`/$filename" fi } SELF=$(readlink_f "$0") SCRIPT_PATH=$(dirname "$SELF") exec "$SCRIPT_PATH"/elixir --no-halt --erl "-user Elixir.IEx.CLI" +iex "$@" elixir-lang-1.1.0~0.20150708/bin/iex.bat000066400000000000000000000001211254730255300171340ustar00rootroot00000000000000@echo off call "%~dp0\elixir.bat" +iex --erl "-user Elixir.IEx.CLI" --no-halt %* elixir-lang-1.1.0~0.20150708/bin/mix000077500000000000000000000000551254730255300164100ustar00rootroot00000000000000#!/usr/bin/env elixir Mix.start Mix.CLI.main elixir-lang-1.1.0~0.20150708/bin/mix.bat000066400000000000000000000001021254730255300171430ustar00rootroot00000000000000@echo off call "%~dp0\elixir.bat" -e Mix.start -e Mix.CLI.main %* elixir-lang-1.1.0~0.20150708/bin/mix.ps1000066400000000000000000000011001254730255300170770ustar00rootroot00000000000000# Store path to mix.bat as a FileInfo object $mixBatPath = (Get-ChildItem (((Get-ChildItem $MyInvocation.MyCommand.Path).Directory.FullName) + '\mix.bat')) $newArgs = @() for ($i = 0; $i -lt $args.length; $i++) { if ($args[$i] -is [array]) { # Commas created the array so we need to reintroduce those commas for ($j = 0; $j -lt $args[$i].length - 1; $j++) { $newArgs += ($args[$i][$j] + ',') } $newArgs += $args[$i][-1] } else { $newArgs += $args[$i] } } # Corrected arguments are ready to pass to batch file & $mixBatPath $newArgs elixir-lang-1.1.0~0.20150708/lib/000077500000000000000000000000001254730255300156635ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/000077500000000000000000000000001254730255300164445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/lib/000077500000000000000000000000001254730255300172125ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex.ex000066400000000000000000000147051254730255300203400ustar00rootroot00000000000000defmodule EEx.SyntaxError do defexception [:message, :file, :line] def message(exception) do "#{exception.file}:#{exception.line}: #{exception.message}" end end defmodule EEx do @moduledoc ~S""" EEx stands for Embedded Elixir. It allows you to embed Elixir code inside a string in a robust way: iex> EEx.eval_string "foo <%= bar %>", [bar: "baz"] "foo baz" ## API This module provides 3 main APIs for you to use: 1. Evaluate a string (`eval_string`) or a file (`eval_file`) directly. This is the simplest API to use but also the slowest, since the code is evaluated and not compiled before. 2. Define a function from a string (`function_from_string`) or a file (`function_from_file`). This allows you to embed the template as a function inside a module which will then be compiled. This is the preferred API if you have access to the template at compilation time. 3. Compile a string (`compile_string`) or a file (`compile_file`) into Elixir syntax tree. This is the API used by both functions above and is available to you if you want to provide your own ways of handling the compiled template. ## Options All functions in this module accepts EEx-related options. They are: * `:line` - the line to be used as the template start. Defaults to 1. * `:file` - the file to be used in the template. Defaults to the given file the template is read from or to "nofile" when compiling from a string. * `:engine` - the EEx engine to be used for compilation. ## Engine EEx has the concept of engines which allows you to modify or transform the code extracted from the given string or file. By default, `EEx` uses the `EEx.SmartEngine` that provides some conveniences on top of the simple `EEx.Engine`. ### Tags `EEx.SmartEngine` supports the following tags: <% Elixir expression - inline with output %> <%= Elixir expression - replace with result %> <%% EEx quotation - returns the contents inside %> <%# Comments - they are discarded from source %> All expressions that output something to the template **must** use the equals sign (`=`). Since everything in Elixir is an expression, there are no exceptions for this rule. For example, while some template languages would special- case `if` clauses, they are treated the same in EEx and also require `=` in order to have their result printed: <%= if true do %> It is obviously true <% else %> This will never appear <% end %> Notice that different engines may have different rules for each tag. Other tags may be added in future versions. ### Macros `EEx.SmartEngine` also adds some macros to your template. An example is the `@` macro which allows easy data access in a template: iex> EEx.eval_string "<%= @foo %>", assigns: [foo: 1] "1" In other words, `<%= @foo %>` is simply translated to: <%= Dict.get assigns, :foo %> The assigns extension is useful when the number of variables required by the template is not specified at compilation time. """ @doc """ Generates a function definition from the string. The kind (`:def` or `:defp`) must be given, the function name, its arguments and the compilation options. ## Examples iex> defmodule Sample do ...> require EEx ...> EEx.function_from_string :def, :sample, "<%= a + b %>", [:a, :b] ...> end iex> Sample.sample(1, 2) "3" """ defmacro function_from_string(kind, name, source, args \\ [], options \\ []) do quote bind_quoted: binding do info = Keyword.merge [file: __ENV__.file, line: __ENV__.line], options args = Enum.map args, fn arg -> {arg, [line: info[:line]], nil} end compiled = EEx.compile_string(source, info) case kind do :def -> def(unquote(name)(unquote_splicing(args)), do: unquote(compiled)) :defp -> defp(unquote(name)(unquote_splicing(args)), do: unquote(compiled)) end end end @doc """ Generates a function definition from the file contents. The kind (`:def` or `:defp`) must be given, the function name, its arguments and the compilation options. This function is useful in case you have templates but you want to precompile inside a module for speed. ## Examples # sample.eex <%= a + b %> # sample.ex defmodule Sample do require EEx EEx.function_from_file :def, :sample, "sample.eex", [:a, :b] end # iex Sample.sample(1, 2) #=> "3" """ defmacro function_from_file(kind, name, file, args \\ [], options \\ []) do quote bind_quoted: binding do info = Keyword.merge options, [file: file, line: 1] args = Enum.map args, fn arg -> {arg, [line: 1], nil} end compiled = EEx.compile_file(file, info) @external_resource file @file file case kind do :def -> def(unquote(name)(unquote_splicing(args)), do: unquote(compiled)) :defp -> defp(unquote(name)(unquote_splicing(args)), do: unquote(compiled)) end end end @doc """ Get a string `source` and generate a quoted expression that can be evaluated by Elixir or compiled to a function. """ def compile_string(source, options \\ []) do EEx.Compiler.compile(source, options) end @doc """ Get a `filename` and generate a quoted expression that can be evaluated by Elixir or compiled to a function. """ def compile_file(filename, options \\ []) do options = Keyword.merge options, [file: filename, line: 1] compile_string(File.read!(filename), options) end @doc """ Get a string `source` and evaluate the values using the `bindings`. ## Examples iex> EEx.eval_string "foo <%= bar %>", [bar: "baz"] "foo baz" """ def eval_string(source, bindings \\ [], options \\ []) do compiled = compile_string(source, options) do_eval(compiled, bindings, options) end @doc """ Get a `filename` and evaluate the values using the `bindings`. ## Examples # sample.eex foo <%= bar %> # iex EEx.eval_file "sample.eex", [bar: "baz"] #=> "foo baz" """ def eval_file(filename, bindings \\ [], options \\ []) do options = Keyword.put options, :file, filename compiled = compile_file(filename, options) do_eval(compiled, bindings, options) end ### Helpers defp do_eval(compiled, bindings, options) do {result, _} = Code.eval_quoted(compiled, bindings, options) result end end elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex/000077500000000000000000000000001254730255300177735ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex/compiler.ex000066400000000000000000000103511254730255300221430ustar00rootroot00000000000000defmodule EEx.Compiler do @moduledoc false # When changing this setting, don't forget to update the docs for EEx @default_engine EEx.SmartEngine @doc """ This is the compilation entry point. It glues the tokenizer and the engine together by handling the tokens and invoking the engine every time a full expression or text is received. """ def compile(source, opts) do file = opts[:file] || "nofile" line = opts[:line] || 1 trim = opts[:trim] || false case EEx.Tokenizer.tokenize(source, line, trim: trim) do {:ok, tokens} -> state = %{engine: opts[:engine] || @default_engine, file: file, line: line, quoted: [], start_line: nil} generate_buffer(tokens, "", [], state) {:error, line, message} -> raise EEx.SyntaxError, line: line, file: file, message: message end end # Generates the buffers by handling each expression from the tokenizer defp generate_buffer([{:text, chars}|t], buffer, scope, state) do buffer = state.engine.handle_text(buffer, IO.chardata_to_string(chars)) generate_buffer(t, buffer, scope, state) end defp generate_buffer([{:expr, line, mark, chars}|t], buffer, scope, state) do expr = Code.string_to_quoted!(chars, [line: line, file: state.file]) buffer = state.engine.handle_expr(buffer, IO.chardata_to_string(mark), expr) generate_buffer(t, buffer, scope, state) end defp generate_buffer([{:start_expr, start_line, mark, chars}|t], buffer, scope, state) do {contents, line, t} = look_ahead_text(t, start_line, chars) {contents, t} = generate_buffer(t, "", [contents|scope], %{state | quoted: [], line: line, start_line: start_line}) buffer = state.engine.handle_expr(buffer, IO.chardata_to_string(mark), contents) generate_buffer(t, buffer, scope, state) end defp generate_buffer([{:middle_expr, line, _, chars}|t], buffer, [current|scope], state) do {wrapped, state} = wrap_expr(current, line, buffer, chars, state) generate_buffer(t, "", [wrapped|scope], %{state | line: line}) end defp generate_buffer([{:end_expr, line, _, chars}|t], buffer, [current|_], state) do {wrapped, state} = wrap_expr(current, line, buffer, chars, state) tuples = Code.string_to_quoted!(wrapped, [line: state.start_line, file: state.file]) buffer = insert_quoted(tuples, state.quoted) {buffer, t} end defp generate_buffer([{:end_expr, line, _, chars}|_], _buffer, [], state) do raise EEx.SyntaxError, message: "unexpected token #{inspect chars}", file: state.file, line: line end defp generate_buffer([], buffer, [], state) do state.engine.handle_body(buffer) end defp generate_buffer([], _buffer, _scope, state) do raise EEx.SyntaxError, message: "unexpected end of string, expected a closing '<% end %>'", file: state.file, line: state.line end # Creates a placeholder and wrap it inside the expression block defp wrap_expr(current, line, buffer, chars, state) do new_lines = List.duplicate(?\n, line - state.line) key = length(state.quoted) placeholder = '__EEX__(' ++ Integer.to_char_list(key) ++ ');' {current ++ placeholder ++ new_lines ++ chars, %{state | quoted: [{key, buffer}|state.quoted]}} end # Look text ahead on expressions defp look_ahead_text([{:text, text}, {:middle_expr, line, _, chars}|t]=list, start, contents) do if only_spaces?(text) do {contents ++ text ++ chars, line, t} else {contents, start, list} end end defp look_ahead_text(t, start, contents) do {contents, start, t} end defp only_spaces?(chars) do Enum.all?(chars, &(&1 in [?\s, ?\t, ?\r, ?\n])) end # Changes placeholder to real expression defp insert_quoted({:__EEX__, _, [key]}, quoted) do {^key, value} = List.keyfind quoted, key, 0 value end defp insert_quoted({left, line, right}, quoted) do {insert_quoted(left, quoted), line, insert_quoted(right, quoted)} end defp insert_quoted({left, right}, quoted) do {insert_quoted(left, quoted), insert_quoted(right, quoted)} end defp insert_quoted(list, quoted) when is_list(list) do Enum.map list, &insert_quoted(&1, quoted) end defp insert_quoted(other, _quoted) do other end end elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex/engine.ex000066400000000000000000000057531254730255300216100ustar00rootroot00000000000000defmodule EEx.Engine do @moduledoc ~S""" Basic EEx engine that ships with Elixir. An engine needs to implement three functions: * `handle_body(quoted)` - receives the final built quoted expression, should do final post-processing and return a quoted expression. * `handle_text(buffer, text)` - it receives the buffer, the text and must return a new quoted expression. * `handle_expr(buffer, marker, expr)` - it receives the buffer, the marker, the expr and must return a new quoted expression. The marker is what follows exactly after `<%`. For example, `<% foo %>` has an empty marker, but `<%= foo %>` has `"="` as marker. The allowed markers so far are: `""` and `"="`. Read `handle_expr/3` below for more information about the markers implemented by default by this engine. `EEx.Engine` can be used directly if one desires to use the default implementations for the functions above. """ use Behaviour defcallback handle_body(Macro.t) :: Macro.t defcallback handle_text(Macro.t, String.t) :: Macro.t defcallback handle_expr(Macro.t, String.t, Macro.t) :: Macro.t @doc false defmacro __using__(_) do quote do @behaviour EEx.Engine def handle_body(body) do EEx.Engine.handle_body(body) end def handle_text(buffer, text) do EEx.Engine.handle_text(buffer, text) end def handle_expr(buffer, marker, expr) do EEx.Engine.handle_expr(buffer, marker, expr) end defoverridable [handle_body: 1, handle_expr: 3, handle_text: 2] end end @doc """ Handles assigns in quoted expressions. This can be added to any custom engine by invoking `handle_assign/1` with `Macro.prewalk/2`: def handle_expr(buffer, token, expr) do expr = Macro.prewalk(expr, &EEx.Engine.handle_assign/1) EEx.Engine.handle_expr(buffer, token, expr) end """ def handle_assign({:@, meta, [{name, _, atom}]}) when is_atom(name) and is_atom(atom) do line = meta[:line] || 0 quote line: line, do: Dict.get(var!(assigns), unquote(name)) end def handle_assign(arg) do arg end @doc """ The default implementation simply returns the given expression. """ def handle_body(quoted) do quoted end @doc """ The default implementation simply concatenates text to the buffer. """ def handle_text(buffer, text) do quote do: unquote(buffer) <> unquote(text) end @doc """ Implements expressions according to the markers. <% Elixir expression - inline with output %> <%= Elixir expression - replace with result %> All other markers are not implemented by this engine. """ @spec handle_expr(Macro.t, String.t, Macro.t) :: Macro.t def handle_expr(buffer, "=", expr) do quote do tmp1 = unquote(buffer) tmp1 <> String.Chars.to_string(unquote(expr)) end end def handle_expr(buffer, "", expr) do quote do tmp2 = unquote(buffer) unquote(expr) tmp2 end end end elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex/smart_engine.ex000066400000000000000000000017101254730255300230030ustar00rootroot00000000000000defmodule EEx.SmartEngine do @moduledoc """ The default engine used by EEx. It includes assigns (like `@foo`) and possibly other conveniences in the future. ## Examples iex> EEx.eval_string("<%= @foo %>", assigns: [foo: 1]) "1" In the example above, we can access the value `foo` under the binding `assigns` using `@foo`. This is useful because a template, after being compiled, can receive different assigns and would not require recompilation for each variable set. Assigns can also be used when compiled to a function: # sample.eex <%= @a + @b %> # sample.ex defmodule Sample do require EEx EEx.function_from_file :def, :sample, "sample.eex", [:assigns] end # iex Sample.sample(a: 1, b: 2) #=> "3" """ use EEx.Engine def handle_expr(buffer, mark, expr) do expr = Macro.prewalk(expr, &EEx.Engine.handle_assign/1) super(buffer, mark, expr) end end elixir-lang-1.1.0~0.20150708/lib/eex/lib/eex/tokenizer.ex000066400000000000000000000130311254730255300223410ustar00rootroot00000000000000defmodule EEx.Tokenizer do @moduledoc false @doc """ Tokenizes the given char list or binary. It returns {:ok, list} with the following tokens: * `{:text, contents}` * `{:expr, line, marker, contents}` * `{:start_expr, line, marker, contents}` * `{:middle_expr, line, marker, contents}` * `{:end_expr, line, marker, contents}` Or `{:error, line, error}` in case of errors. """ def tokenize(bin, line, opts \\ []) def tokenize(bin, line, opts) when is_binary(bin) do tokenize(String.to_char_list(bin), line, opts) end def tokenize(list, line, opts) do tokenize(list, line, opts, [], []) end defp tokenize('<%%' ++ t, line, opts, buffer, acc) do tokenize t, line, opts, [?%, ?<|buffer], acc end defp tokenize('<%#' ++ t, line, opts, buffer, acc) do case expr(t, line, []) do {:error, _, _} = error -> error {:ok, _, new_line, rest} -> {rest, new_line, buffer} = trim_if_needed(rest, new_line, opts, buffer, acc) tokenize rest, new_line, opts, buffer, acc end end defp tokenize('<%' ++ t, line, opts, buffer, acc) do {marker, t} = retrieve_marker(t) case expr(t, line, []) do {:error, _, _} = error -> error {:ok, expr, new_line, rest} -> token = token_name(expr) {rest, new_line, buffer} = trim_if_needed(rest, new_line, opts, buffer, acc) acc = tokenize_text(buffer, acc) final = {token, line, marker, Enum.reverse(expr)} tokenize rest, new_line, opts, [], [final | acc] end end defp tokenize('\n' ++ t, line, opts, buffer, acc) do tokenize t, line + 1, opts, [?\n|buffer], acc end defp tokenize([h|t], line, opts, buffer, acc) do tokenize t, line, opts, [h|buffer], acc end defp tokenize([], _line, _opts, buffer, acc) do {:ok, Enum.reverse(tokenize_text(buffer, acc))} end # Retrieve marker for <% defp retrieve_marker('=' ++ t) do {'=', t} end defp retrieve_marker(t) do {'', t} end # Tokenize an expression until we find %> defp expr([?%, ?>|t], line, buffer) do {:ok, buffer, line, t} end defp expr('\n' ++ t, line, buffer) do expr t, line + 1, [?\n|buffer] end defp expr([h|t], line, buffer) do expr t, line, [h|buffer] end defp expr([], line, _buffer) do {:error, line, "missing token '%>'"} end # Receive an expression content and check # if it is a start, middle or an end token. # # Start tokens finish with `do` and `fn ->` # Middle tokens are marked with `->` or keywords # End tokens contain only the end word and optionally `)` defp token_name([h|t]) when h in [?\s, ?\t, ?)] do token_name(t) end defp token_name('od' ++ [h|_]) when h in [?\s, ?\t, ?)] do :start_expr end defp token_name('>-' ++ rest) do rest = Enum.reverse(rest) # Tokenize the remaining passing check_terminators as # false, which relax the tokenizer to not error on # unmatched pairs. Then, we check if there is a "fn" # token and, if so, it is not followed by an "end" # token. If this is the case, we are on a start expr. case :elixir_tokenizer.tokenize(rest, 1, file: "eex", check_terminators: false) do {:ok, _line, _column, tokens} -> tokens = Enum.reverse(tokens) fn_index = fn_index(tokens) if fn_index && end_index(tokens) > fn_index do :start_expr else :middle_expr end _error -> :middle_expr end end defp token_name('esle' ++ t), do: check_spaces(t, :middle_expr) defp token_name('retfa' ++ t), do: check_spaces(t, :middle_expr) defp token_name('hctac' ++ t), do: check_spaces(t, :middle_expr) defp token_name('eucser' ++ t), do: check_spaces(t, :middle_expr) defp token_name('dne' ++ t), do: check_spaces(t, :end_expr) defp token_name(_) do :expr end defp fn_index(tokens) do Enum.find_index tokens, fn {:fn_paren, _} -> true {:fn, _} -> true _ -> false end end defp end_index(tokens) do Enum.find_index(tokens, &match?({:end, _}, &1)) || :infinity end defp check_spaces(string, token) do if Enum.all?(string, &(&1 in [?\s, ?\t])) do token else :expr end end # Tokenize the buffered text by appending # it to the given accumulator. defp tokenize_text([], acc) do acc end defp tokenize_text(buffer, acc) do [{:text, Enum.reverse(buffer)} | acc] end # If trim mode is enabled and the token is on a line with # only itself and whitespace, trim the whitespace around it, # including the line break following it if there is one. defp trim_if_needed(rest, line, opts, buffer, acc) do original = {rest, line, buffer} if opts[:trim] do case {trim_left(buffer, acc), trim_right(rest, line)} do {{true, new_buffer}, {true, new_rest, new_line}} -> {new_rest, new_line, new_buffer} _ -> original end else original end end defp trim_left(buffer, acc) do case {trim_whitespace(buffer), acc} do {[?\n|_] = trimmed_buffer, _} -> {true, trimmed_buffer} {[], []} -> {true, []} _ -> {false, buffer} end end defp trim_right(rest, line) do case trim_whitespace(rest) do [?\r, ?\n|trimmed_rest] -> {true, trimmed_rest, line + 1} [?\n|trimmed_rest] -> {true, trimmed_rest, line + 1} [] -> {true, [], line} _ -> {false, rest, line} end end defp trim_whitespace([h|t]) when h == ?\s or h == ?\t do trim_whitespace(t) end defp trim_whitespace(list) do list end end elixir-lang-1.1.0~0.20150708/lib/eex/mix.exs000066400000000000000000000002301254730255300177550ustar00rootroot00000000000000defmodule EEx.Mixfile do use Mix.Project def project do [app: :eex, version: System.version, build_per_environment: false] end end elixir-lang-1.1.0~0.20150708/lib/eex/test/000077500000000000000000000000001254730255300174235ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/test/eex/000077500000000000000000000000001254730255300202045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/test/eex/smart_engine_test.exs000066400000000000000000000016761254730255300244510ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule EEx.SmartEngineTest do use ExUnit.Case, async: true test "evaluates simple string" do assert_eval "foo bar", "foo bar" end test "evaluates with assigns as keywords" do assert_eval "1", "<%= @foo %>", assigns: [foo: 1] end test "evaluates with assigns as a map" do assert_eval "1", "<%= @foo %>", assigns: %{foo: 1} end test "evaluates with loops" do assert_eval "1\n2\n3\n", "<%= for x <- [1, 2, 3] do %><%= x %>\n<% end %>" end test "compiled preserved line numbers" do result = EEx.compile_string("<%= @hello %>", engine: EEx.SmartEngine) Macro.prewalk(result, fn {_left, meta, _right} -> assert Keyword.get(meta, :line, 0) in [0, 1] _ -> :ok end) end defp assert_eval(expected, actual, binding \\ []) do result = EEx.eval_string(actual, binding, file: __ENV__.file) assert result == expected end end elixir-lang-1.1.0~0.20150708/lib/eex/test/eex/tokenizer_test.exs000066400000000000000000000104261254730255300240010ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule EEx.TokenizerTest do use ExUnit.Case, async: true require EEx.Tokenizer, as: T test "simple chars lists" do assert T.tokenize('foo', 1) == {:ok, [{:text, 'foo'}]} end test "simple strings" do assert T.tokenize("foo", 1) == {:ok, [{:text, 'foo'}]} end test "strings with embedded code" do assert T.tokenize('foo <% bar %>', 1) == {:ok, [{:text, 'foo '}, {:expr, 1, '', ' bar '}]} end test "strings with embedded equals code" do assert T.tokenize('foo <%= bar %>', 1) == {:ok, [{:text, 'foo '}, {:expr, 1, '=', ' bar '}]} end test "strings with more than one line" do assert T.tokenize('foo\n<%= bar %>', 1) == {:ok, [{:text, 'foo\n'}, {:expr, 2, '=', ' bar '}]} end test "strings with more than one line and expression with more than one line" do string = ''' foo <%= bar baz %> <% foo %> ''' assert T.tokenize(string, 1) == {:ok, [ {:text, 'foo '}, {:expr, 1, '=', ' bar\n\nbaz '}, {:text, '\n'}, {:expr, 4, '', ' foo '}, {:text, '\n'} ]} end test "quotation" do assert T.tokenize('foo <%% true %>', 1) == {:ok, [ {:text, 'foo <% true %>'} ]} end test "quotation with do/end" do assert T.tokenize('foo <%% true do %>bar<%% end %>', 1) == {:ok, [ {:text, 'foo <% true do %>bar<% end %>'} ]} end test "quotation with interpolation" do assert T.tokenize('a <%% b <%= c %> <%= d %> e %> f', 1) == {:ok, [ {:text, 'a <% b '}, {:expr, 1, '=', ' c '}, {:text, ' '}, {:expr, 1, '=', ' d '}, {:text, ' e %> f'} ]} assert T.tokenize('<%%% a <%%= b %> c %>', 1) == {:ok, [ {:text, '<%% a <%= b %> c %>'} ]} end test "comments" do assert T.tokenize('foo <%# true %>', 1) == {:ok, [ {:text, 'foo '} ]} end test "comments with do/end" do assert T.tokenize('foo <%# true do %>bar<%# end %>', 1) == {:ok, [ {:text, 'foo bar'} ]} end test "strings with embedded do end" do assert T.tokenize('foo <% if true do %>bar<% end %>', 1) == {:ok, [ {:text, 'foo '}, {:start_expr, 1, '', ' if true do '}, {:text, 'bar'}, {:end_expr, 1, '', ' end '} ]} end test "strings with embedded -> end" do assert T.tokenize('foo <% cond do %><% false -> %>bar<% true -> %>baz<% end %>', 1) == {:ok, [ {:text, 'foo '}, {:start_expr, 1, '', ' cond do '}, {:middle_expr, 1, '', ' false -> '}, {:text, 'bar'}, {:middle_expr, 1, '', ' true -> '}, {:text, 'baz'}, {:end_expr, 1, '', ' end '} ]} end test "strings with embedded keywords blocks" do assert T.tokenize('foo <% if true do %>bar<% else %>baz<% end %>', 1) == {:ok, [ {:text, 'foo '}, {:start_expr, 1, '', ' if true do '}, {:text, 'bar'}, {:middle_expr, 1, '', ' else '}, {:text, 'baz'}, {:end_expr, 1, '', ' end '} ]} end test "trim mode" do template = '\t<%= if true do %> \n TRUE \n <% else %>\n FALSE \n <% end %> ' assert T.tokenize(template, 1, trim: true) == {:ok, [ {:start_expr, 1, '=', ' if true do '}, {:text, ' TRUE \n'}, {:middle_expr, 3, '', ' else '}, {:text, ' FALSE \n'}, {:end_expr, 5, '', ' end '} ]} end test "trim mode with comment" do assert T.tokenize(' <%# comment %> \n123', 1, trim: true) == {:ok, [ {:text, '123'} ]} end test "trim mode with CRLF" do assert T.tokenize('0\r\n <%= 12 %> \r\n34', 1, trim: true) == {:ok, [ {:text, '0\r\n'}, {:expr, 2, '=', ' 12 '}, {:text, '34'} ]} end test "trim mode set to false" do assert T.tokenize(' <%= 12 %> \n', 1, trim: false) == {:ok, [ {:text, ' '}, {:expr, 1, '=', ' 12 '}, {:text, ' \n'} ]} end test "trim mode no false positives" do assert_not_trimmed = fn x -> assert T.tokenize(x, 1, trim: true) == T.tokenize(x, 1) end assert_not_trimmed.('foo <%= "bar" %> ') assert_not_trimmed.('\n <%= "foo" %>bar') assert_not_trimmed.(' <%% hello %> ') assert_not_trimmed.(' <%= 01 %><%= 23 %>\n') end test "raise syntax error when there is start mark and no end mark" do assert T.tokenize('foo <% :bar', 1) == {:error, 1, "missing token '%>'"} end end elixir-lang-1.1.0~0.20150708/lib/eex/test/eex_test.exs000066400000000000000000000221331254730255300217650ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ require EEx defmodule EExTest.Compiled do def before_compile do fill_in_stacktrace {__ENV__.line, hd(tl(System.stacktrace))} end EEx.function_from_string :def, :string_sample, "<%= a + b %>", [:a, :b] filename = Path.join(__DIR__, "fixtures/eex_template_with_bindings.eex") EEx.function_from_file :defp, :private_file_sample, filename, [:bar] filename = Path.join(__DIR__, "fixtures/eex_template_with_bindings.eex") EEx.function_from_file :def, :public_file_sample, filename, [:bar] def file_sample(arg), do: private_file_sample(arg) def after_compile do fill_in_stacktrace {__ENV__.line, hd(tl(System.stacktrace))} end @file "unknown" def unknown do fill_in_stacktrace {__ENV__.line, hd(tl(System.stacktrace))} end defp fill_in_stacktrace do try do :erlang.error "failed" catch :error, _ -> System.stacktrace end end end defmodule Clause do defmacro defclause(expr, block) do quote do def unquote(expr), unquote(block) end end end defmodule EExTest do use ExUnit.Case, async: true doctest EEx doctest EEx.Engine doctest EEx.SmartEngine test "evaluates simple string" do assert_eval "foo bar", "foo bar" end test "evaluates with embedded" do assert_eval "foo bar", "foo <%= :bar %>" end test "evaluates with embedded and the binding" do assert EEx.eval_string("foo <%= bar %>", [bar: 1]) == "foo 1" end test "evaluates with embedded do end" do assert_eval "foo bar", "foo <%= if true do %>bar<% end %>" end test "evaluates with embedded do end and eval the expression" do assert_eval "foo ", "foo <%= if false do %>bar<% end %>" end test "evaluates with embedded do end and nested print expression" do assert_eval "foo bar", "foo <%= if true do %><%= :bar %><% end %>" end test "evaluates with embedded do end and nested expressions" do assert_eval "foo bar baz", "foo <%= if true do %>bar <% Process.put(:eex_text, 1) %><%= :baz %><% end %>" assert Process.get(:eex_text) == 1 end test "evaluates with embedded middle expression" do assert_eval "foo bar", "foo <%= if true do %>bar<% else %>baz<% end %>" end test "evaluates with embedded middle expression and eval the expression" do assert_eval "foo baz", "foo <%= if false do %>bar<% else %>baz<% end %>" end test "evaluates with nested start expression" do assert_eval "foo bar", "foo <%= if true do %><%= if true do %>bar<% end %><% end %>" end test "evaluates with nested middle expression" do assert_eval "foo baz", "foo <%= if true do %><%= if false do %>bar<% else %>baz<% end %><% end %>" end test "evaluates with parentheses after end in end token" do assert_eval " 101 102 103 ", "<%= Enum.map([1,2,3], (fn x -> %> <%= 100 + x %> <% end) ) %>" end test "evaluates with defined variable" do assert_eval "foo 1", "foo <% bar = 1 %><%= bar %>" end test "evaluates with require code" do assert_eval "foo 1,2,3", "foo <% require Enum, as: E %><%= E.join [1, 2, 3], \",\" %>" end test "evaluates with end of token" do assert_eval "foo bar %>", "foo bar %>" end test "raises a syntax error when the token is invalid" do assert_raise EEx.SyntaxError, "nofile:1: missing token '%>'", fn -> EEx.compile_string "foo <%= bar" end end test "raises a syntax error when end expression is found without a start expression" do assert_raise EEx.SyntaxError, "nofile:1: unexpected token ' end '", fn -> EEx.compile_string "foo <% end %>" end end test "raises a syntax error when start expression is found without an end expression" do assert_raise EEx.SyntaxError, "nofile:2: unexpected end of string, expected a closing '<% end %>'", fn -> EEx.compile_string "foo\n<% if true do %>" end end test "raises a syntax error when nested end expression is found without a start expression" do assert_raise EEx.SyntaxError, "nofile:1: unexpected token ' end '", fn -> EEx.compile_string "foo <% if true do %><% end %><% end %>" end end test "respects line numbers" do expected = """ foo 2 """ string = """ foo <%= __ENV__.line %> """ assert_eval expected, string end test "respects line numbers inside nested expressions" do expected = """ foo 3 5 """ string = """ foo <%= if true do %> <%= __ENV__.line %> <% end %> <%= __ENV__.line %> """ assert_eval expected, string end test "respects line numbers inside start expression" do expected = """ foo true 5 """ string = """ foo <%= if __ENV__.line == 2 do %> <%= true %> <% end %> <%= __ENV__.line %> """ assert_eval expected, string end test "respects line numbers inside middle expression with ->" do expected = """ foo true 7 """ string = """ foo <%= cond do %> <% false -> %> false <% __ENV__.line == 4 -> %> <%= true %> <% end %> <%= __ENV__.line %> """ assert_eval expected, string end test "respects line number inside middle expressions with keywords" do expected = """ foo 5 7 """ string = """ foo <%= if false do %> <%= __ENV__.line %> <% else %> <%= __ENV__.line %> <% end %> <%= __ENV__.line %> """ assert_eval expected, string end test "properly handle functions" do expected = """ Number 1 Number 2 Number 3 """ string = """ <%= Enum.map [1, 2, 3], fn x -> %> Number <%= x %> <% end %> """ assert_eval expected, string end test "properly handle functions on the left side of clauses" do expected = """ foo true """ string = """ foo <%= cond do %> <% false -> %> false <% fn -> 1 end -> %> <%= true %> <% end %> """ assert_eval expected, string end test "evaluates nested do expressions" do string = """ <% y = ["a", "b", "c"] %> <%= cond do %> <% "a" in y -> %> Good <% true -> %> <% if true do %>true<% else %>false<% end %> Bad <% end %> """ assert_eval "\n\n Good\n \n", string end test "evaluates expressions with buffers" do string = """ <%= 123 %> <% if true do %> <%= 456 %> <% end %> <%= 789 %> """ assert_eval "123\n\n789\n", string end test "for comprehensions" do string = """ <%= for _name <- packages || [] do %> <% end %> <%= all || :done %> """ assert_eval "\ndone\n", string, packages: nil, all: nil end test "unicode" do template = """ • <%= "•" %> • <%= "Jößé Vâlìm" %> Jößé Vâlìm """ result = EEx.eval_string(template) assert result == " • • •\n Jößé Vâlìm Jößé Vâlìm\n" end test "trim mode" do string = "<%= 123 %> \n456\n <%= 789 %>" expected = "123456\n789" assert_eval expected, string, [], trim: true end test "evaluates the source from a given file" do filename = Path.join(__DIR__, "fixtures/eex_template.eex") result = EEx.eval_file(filename) assert result == "foo bar.\n" end test "evaluates the source from a given file with bindings" do filename = Path.join(__DIR__, "fixtures/eex_template_with_bindings.eex") result = EEx.eval_file(filename, [bar: 1]) assert result == "foo 1\n" end test "raises an Exception when there's an error with the given file" do assert_raise File.Error, "could not read file non-existent.eex: no such file or directory", fn -> filename = "non-existent.eex" EEx.compile_file(filename) end end test "sets external resource attribute" do assert EExTest.Compiled.__info__(:attributes)[:external_resource] == [Path.join(__DIR__, "fixtures/eex_template_with_bindings.eex")] end test "defined from string" do assert EExTest.Compiled.string_sample(1, 2) == "3" end test "defined from file" do assert EExTest.Compiled.file_sample(1) == "foo 1\n" assert EExTest.Compiled.public_file_sample(1) == "foo 1\n" end test "defined from file do not affect backtrace" do assert EExTest.Compiled.before_compile == {8, {EExTest.Compiled, :before_compile, 0, [file: to_char_list(Path.relative_to_cwd(__ENV__.file)), line: 7] } } assert EExTest.Compiled.after_compile == {23, {EExTest.Compiled, :after_compile, 0, [file: to_char_list(Path.relative_to_cwd(__ENV__.file)), line: 22] } } assert EExTest.Compiled.unknown == {29, {EExTest.Compiled, :unknown, 0, [file: 'unknown', line: 28] } } end defmodule TestEngine do @behaviour EEx.Engine def handle_body(body) do {:wrapped, body} end def handle_text(buffer, text) do EEx.Engine.handle_text(buffer, text) end def handle_expr(buffer, mark, expr) do EEx.Engine.handle_expr(buffer, mark, expr) end end test "calls handle_body" do assert {:wrapped, "foo"} = EEx.eval_string("foo", [], engine: TestEngine) end defp assert_eval(expected, actual, binding \\ [], opts \\ []) do opts = Enum.into [file: __ENV__.file, engine: EEx.Engine], opts result = EEx.eval_string(actual, binding, opts) assert result == expected end end elixir-lang-1.1.0~0.20150708/lib/eex/test/fixtures/000077500000000000000000000000001254730255300212745ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/eex/test/fixtures/eex_template.eex000066400000000000000000000000431254730255300244500ustar00rootroot00000000000000foo <%= if true do %>bar.<% end %> elixir-lang-1.1.0~0.20150708/lib/eex/test/fixtures/eex_template_with_bindings.eex000066400000000000000000000000171254730255300273610ustar00rootroot00000000000000foo <%= bar %> elixir-lang-1.1.0~0.20150708/lib/eex/test/test_helper.exs000066400000000000000000000000561254730255300224630ustar00rootroot00000000000000ExUnit.start [trace: "--trace" in System.argv]elixir-lang-1.1.0~0.20150708/lib/elixir/000077500000000000000000000000001254730255300171575ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/000077500000000000000000000000001254730255300177255ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/access.ex000066400000000000000000000104131254730255300215230ustar00rootroot00000000000000defprotocol Access do @moduledoc """ Dictionary-like access to data structures via the `foo[bar]` syntax. This module also empowers `Kernel`s nested update functions `Kernel.get_in/2`, `Kernel.put_in/3`, `Kernel.update_in/3` and `Kernel.get_and_update_in/3`. ## Deprecated Currently, the Access protocol is deprecated as there are performance concerns in the current implementation. Since Elixir v1.1, instead of using a protocol, `foo[bar]` will dispatch directly to the `Dict` module. Therefore, while `foo[bar]` will continue to work, extension of the syntax should be done via a custom `Dict` implementation. ## Examples Out of the box, Access works all built-in dictionaries: `Keyword`, `Map` and `HashDict`: iex> keywords = [a: 1, b: 2] iex> keywords[:a] 1 iex> map = %{a: 1, b: 2} iex> map[:a] 1 iex> star_ratings = %{1.0 => "★", 1.5 => "★☆", 2.0 => "★★"} iex> star_ratings[1.5] "★☆" Furthermore, Access transparently ignores `nil` values: iex> keywords = [a: 1, b: 2] iex> keywords[:c][:unknown] nil The key comparison must be implemented using the `===` operator. """ @doc """ Gets the container's value for the given key. """ @spec get(t, term) :: t def get(container, key) @doc """ Gets and updates the container's value for the given key, in a single pass. The argument function `fun` must receive the value for the given `key` (or `nil` if the key doesn't exist in `container`). It must return a tuple containing the `get` value and the new value to be stored in the `container`. This function returns a two-element tuple. The first element is the `get` value, as returned by `fun`. The second element is the container, updated with the value returned by `fun`. """ @spec get_and_update(t, term, (term -> {get, term})) :: {get, t} when get: var def get_and_update(container, key, fun) end defimpl Access, for: List do def get(dict, key) when is_atom(key) do case :lists.keyfind(key, 1, dict) do {^key, value} -> value false -> nil end end def get(_dict, key) do raise ArgumentError, "the access protocol for lists expect the key to be an atom, got: #{inspect key}" end def get_and_update(dict, key, fun) when is_atom(key) do get_and_update(dict, [], key, fun) end defp get_and_update([{key, value}|t], acc, key, fun) do {get, update} = fun.(value) {get, :lists.reverse(acc, [{key, update}|t])} end defp get_and_update([h|t], acc, key, fun) do get_and_update(t, [h|acc], key, fun) end defp get_and_update([], acc, key, fun) do {get, update} = fun.(nil) {get, [{key, update}|:lists.reverse(acc)]} end end defimpl Access, for: [Map, Any] do def get(map, key) do case :maps.find(key, map) do {:ok, value} -> value :error -> nil end end def get_and_update(map, key, fun) do value = case :maps.find(key, map) do {:ok, value} -> value :error -> nil end {get, update} = fun.(value) {get, :maps.put(key, update, map)} end def get!(%{} = map, key) do case :maps.find(key, map) do {:ok, value} -> value :error -> raise KeyError, key: key, term: map end end def get!(other, key) do raise ArgumentError, "could not get key #{inspect key}. Expected map/struct, got: #{inspect other}" end def get_and_update!(%{} = map, key, fun) do case :maps.find(key, map) do {:ok, value} -> {get, update} = fun.(value) {get, :maps.put(key, update, map)} :error -> raise KeyError, key: key, term: map end end def get_and_update!(other, key, _fun) do raise ArgumentError, "could not put/update key #{inspect key}. Expected map/struct, got: #{inspect other}" end end defimpl Access, for: Atom do def get(nil, _) do nil end def get(atom, _) do undefined(atom) end def get_and_update(nil, key, _fun) do raise ArgumentError, "could not put/update key #{inspect key} on a nil value" end def get_and_update(atom, _key, _fun) do undefined(atom) end defp undefined(atom) do raise Protocol.UndefinedError, protocol: @protocol, value: atom, description: "only the nil atom is supported" end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/agent.ex000066400000000000000000000252671254730255300213750ustar00rootroot00000000000000defmodule Agent do @moduledoc """ Agents are a simple abstraction around state. Often in Elixir there is a need to share or store state that must be accessed from different processes or by the same process at different points in time. The Agent module provides a basic server implementation that allows state to be retrieved and updated via a simple API. ## Examples For example, in the Mix tool that ships with Elixir, we need to keep a set of all tasks executed by a given project. Since this set is shared, we can implement it with an Agent: defmodule Mix.TasksServer do def start_link do Agent.start_link(fn -> HashSet.new end, name: __MODULE__) end @doc "Checks if the task has already executed" def executed?(task, project) do item = {task, project} Agent.get(__MODULE__, fn set -> item in set end) end @doc "Marks a task as executed" def put_task(task, project) do item = {task, project} Agent.update(__MODULE__, &Set.put(&1, item)) end @doc "Reset the executed tasks and return the previous list of tasks" def take_all() do Agent.get_and_update(__MODULE__, fn set -> {Enum.into(set, []), HashSet.new} end) end end Note that agents still provide a segregation between the client and server APIs, as seen in GenServers. In particular, all code inside the function passed to the agent is executed by the agent. This distinction is important because you may want to avoid expensive operations inside the agent, as it will effectively block the agent until the request is fulfilled. Consider these two examples: # Compute in the agent/server def get_something(agent) do Agent.get(agent, fn state -> do_something_expensive(state) end) end # Compute in the agent/client def get_something(agent) do Agent.get(agent, &(&1)) |> do_something_expensive() end The first one blocks the agent while the second one copies all the state to the client and executes the operation in the client. The trade-off here is exactly if the data is small enough to be sent to the client cheaply or large enough to require processing on the server (or at least some initial processing). ## Name Registration An Agent is bound to the same name registration rules as GenServers. Read more about it in the `GenServer` docs. ## A word on distributed agents It is important to consider the limitations of distributed agents. Agents provides two APIs, one that works with anonymous functions and another that expects explicit module, function and arguments. In a distributed setup with multiple nodes, the API that accepts anonymous functions only works if the caller (client) and the agent have the same version of the caller module. Keep in mind this issue also shows up when performing "rolling upgrades" with agents. By rolling upgrades we mean the following situation: you wish to deploy a new version of your software by *shutting down* some of your nodes and replacing them with nodes running a new version of the software. In this setup, part of your environment will have one version of a given module and the other part another version (the newer one) of the same module. The best solution is to simply use the explicit module, function and arguments APIs when working with distributed agents. ## Hot code swapping An agent can have its code hot swapped live by simply passing a module, function and args tuple to the update instruction. For example, imagine you have an agent named `:sample` and you want to convert its inner state from some dict structure to a map. It can be done with the following instruction: {:update, :sample, {:advanced, {Enum, :into, [%{}]}}} The agent's state will be added to the given list as the first argument. """ @typedoc "Return values of `start*` functions" @type on_start :: {:ok, pid} | {:error, {:already_started, pid} | term} @typedoc "The agent name" @type name :: atom | {:global, term} | {:via, module, term} @typedoc "The agent reference" @type agent :: pid | {atom, node} | name @typedoc "The agent state" @type state :: term @doc """ Starts an agent linked to the current process with the given function. This is often used to start the agent as part of a supervision tree. Once the agent is spawned, the given function is invoked and its return value is used as the agent state. Note that `start_link` does not return until the given function has returned. ## Options The `:name` option is used for registration as described in the module documentation. If the `:timeout` option is present, the agent is allowed to spend at most the given number of milliseconds on initialization or it will be terminated and the start function will return `{:error, :timeout}`. If the `:debug` option is present, the corresponding function in the [`:sys` module](http://www.erlang.org/doc/man/sys.html) will be invoked. If the `:spawn_opt` option is present, its value will be passed as options to the underlying process as in `Process.spawn/4`. ## Return values If the server is successfully created and initialized, the function returns `{:ok, pid}`, where `pid` is the pid of the server. If an agent with the specified name already exists, the function returns `{:error, {:already_started, pid}}` with the pid of that process. If the given function callback fails with `reason`, the function returns `{:error, reason}`. """ @spec start_link((() -> term), GenServer.options) :: on_start def start_link(fun, options \\ []) when is_function(fun, 0) do GenServer.start_link(Agent.Server, fun, options) end @doc """ Starts an agent linked to the current process with the given module function and arguments. Same as `start_link/2` but a module, function and args are expected instead of an anonymous function. """ @spec start_link(module, atom, [any], GenServer.options) :: on_start def start_link(module, fun, args, options \\ []) do GenServer.start_link(Agent.Server, {module, fun, args}, options) end @doc """ Starts an agent process without links (outside of a supervision tree). See `start_link/2` for more information. """ @spec start((() -> term), GenServer.options) :: on_start def start(fun, options \\ []) when is_function(fun, 0) do GenServer.start(Agent.Server, fun, options) end @doc """ Starts an agent with the given module function and arguments. Similar to `start/2` but a module, function and args are expected instead of an anonymous function. """ @spec start(module, atom, [any], GenServer.options) :: on_start def start(module, fun, args, options \\ []) do GenServer.start(Agent.Server, {module, fun, args}, options) end @doc """ Gets an agent value via the given function. The function `fun` is sent to the `agent` which invokes the function passing the agent state. The result of the function invocation is returned. A timeout can also be specified (it has a default value of 5000). """ @spec get(agent, (state -> a), timeout) :: a when a: var def get(agent, fun, timeout \\ 5000) when is_function(fun, 1) do GenServer.call(agent, {:get, fun}, timeout) end @doc """ Gets an agent value via the given function. Same as `get/3` but a module, function and args are expected instead of an anonymous function. The state is added as first argument to the given list of args. """ @spec get(agent, module, atom, [term], timeout) :: any def get(agent, module, fun, args, timeout \\ 5000) do GenServer.call(agent, {:get, {module, fun, args}}, timeout) end @doc """ Gets and updates the agent state in one operation. The function `fun` is sent to the `agent` which invokes the function passing the agent state. The function must return a tuple with two elements, the first being the value to return (i.e. the `get` value) and the second one is the new state. A timeout can also be specified (it has a default value of 5000). """ @spec get_and_update(agent, (state -> {a, state}), timeout) :: a when a: var def get_and_update(agent, fun, timeout \\ 5000) when is_function(fun, 1) do GenServer.call(agent, {:get_and_update, fun}, timeout) end @doc """ Gets and updates the agent state in one operation. Same as `get_and_update/3` but a module, function and args are expected instead of an anonymous function. The state is added as first argument to the given list of args. """ @spec get_and_update(agent, module, atom, [term], timeout) :: any def get_and_update(agent, module, fun, args, timeout \\ 5000) do GenServer.call(agent, {:get_and_update, {module, fun, args}}, timeout) end @doc """ Updates the agent state. The function `fun` is sent to the `agent` which invokes the function passing the agent state. The function must return the new state. A timeout can also be specified (it has a default value of 5000). This function always returns `:ok`. """ @spec update(agent, (state -> state), timeout) :: :ok def update(agent, fun, timeout \\ 5000) when is_function(fun, 1) do GenServer.call(agent, {:update, fun}, timeout) end @doc """ Updates the agent state. Same as `update/3` but a module, function and args are expected instead of an anonymous function. The state is added as first argument to the given list of args. """ @spec update(agent, module, atom, [term], timeout) :: :ok def update(agent, module, fun, args, timeout \\ 5000) do GenServer.call(agent, {:update, {module, fun, args}}, timeout) end @doc """ Performs a cast (fire and forget) operation on the agent state. The function `fun` is sent to the `agent` which invokes the function passing the agent state. The function must return the new state. Note that `cast` returns `:ok` immediately, regardless of whether the destination node or agent exists. """ @spec cast(agent, (state -> state)) :: :ok def cast(agent, fun) when is_function(fun, 1) do GenServer.cast(agent, {:cast, fun}) end @doc """ Performs a cast (fire and forget) operation on the agent state. Same as `cast/2` but a module, function and args are expected instead of an anonymous function. The state is added as first argument to the given list of args. """ @spec cast(agent, module, atom, [term]) :: :ok def cast(agent, module, fun, args) do GenServer.cast(agent, {:cast, {module, fun, args}}) end @doc """ Stops the agent. Returns `:ok` if the agent is stopped within the given `timeout`. """ @spec stop(agent, timeout) :: :ok def stop(agent, timeout \\ 5000) do GenServer.call(agent, :stop, timeout) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/agent/000077500000000000000000000000001254730255300210235ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/agent/server.ex000066400000000000000000000022531254730255300226710ustar00rootroot00000000000000defmodule Agent.Server do @moduledoc false use GenServer def init(fun) do {:ok, run(fun, [])} end def handle_call({:get, fun}, _from, state) do {:reply, run(fun, [state]), state} end def handle_call({:get_and_update, fun}, _from, state) do {reply, state} = run(fun, [state]) {:reply, reply, state} end def handle_call({:update, fun}, _from, state) do {:reply, :ok, run(fun, [state])} end def handle_call(:stop, _from, state) do {:stop, :normal, :ok, state} end def handle_call(msg, from, state) do super(msg, from, state) end def handle_cast({:cast, fun}, state) do {:noreply, run(fun, [state])} end def handle_cast(msg, state) do super(msg, state) end def code_change(_old, state, fun) do {:ok, run(fun, [state])} end def terminate(_reason, _state) do # There is a race condition if the agent is # restarted too fast and it is registered. try do self |> :erlang.process_info(:registered_name) |> elem(1) |> Process.unregister rescue _ -> :ok end :ok end defp run({m, f, a}, extra), do: apply(m, f, extra ++ a) defp run(fun, extra), do: apply(fun, extra) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/application.ex000066400000000000000000000326401254730255300225730ustar00rootroot00000000000000defmodule Application do @moduledoc """ A module for working with applications and defining application callbacks. In Elixir (actually, in Erlang/OTP), an application is a component implementing some specific functionality, that can be started and stopped as a unit, and which can be re-used in other systems. Applications are defined with an application file named `APP.app` where `APP` is the application name, usually in `underscore_case`. The application file must reside in the same `ebin` directory as the compiled modules of the application. In Elixir, Mix is responsible for compiling your source code and generating your application `.app` file. Furthermore, Mix is also responsible for configuring, starting and stopping your application and its dependencies. For this reason, this documentation will focus on the remaining aspects of your application: the application environment and the application callback module. You can learn more about Mix generation of `.app` files by typing `mix help compile.app`. ## Application environment Once an application is started, OTP provides an application environment that can be used to configure the application. Assuming you are inside a Mix project, you can edit the `application` function in the `mix.exs` file to the following: def application do [env: [hello: :world]] end In the application function, we can define the default environment values for our application. By starting your application with `iex -S mix`, you can access the default value: Application.get_env(:APP_NAME, :hello) #=> :world It is also possible to put and delete values from the application value, including new values that are not defined in the environment file (although this should be avoided). In the future, we plan to support configuration files which allow developers to configure the environment of their dependencies. Keep in mind that each application is responsible for its environment. Do not use the functions in this module for directly accessing or modifying the environment of other applications (as it may lead to inconsistent data in the application environment). ## Application module callback Often times, an application defines a supervision tree that must be started and stopped when the application starts and stops. For such, we need to define an application module callback. The first step is to define the module callback in the application definition in the `mix.exs` file: def application do [mod: {MyApp, []}] end Our application now requires the `MyApp` module to provide an application callback. This can be done by invoking `use Application` in that module and defining a `start/2` callback, for example: defmodule MyApp do use Application def start(_type, _args) do MyApp.Supervisor.start_link() end end `start/2` typically returns `{:ok, pid}` or `{:ok, pid, state}` where `pid` identifies the supervision tree and `state` is the application state. `args` is the second element of the tuple given to the `:mod` option. The `type` argument passed to `start/2` is usually `:normal` unless in a distributed setup where application takeovers and failovers are configured. This particular aspect of applications is explained in more detail in the OTP documentation: * http://www.erlang.org/doc/man/application.html * http://www.erlang.org/doc/design_principles/applications.html A developer may also implement the `stop/1` callback (automatically defined by `use Application`) which does any application cleanup. It receives the application state and can return any value. Note that shutting down the supervisor is automatically handled by the VM. """ @doc false defmacro __using__(_) do quote location: :keep do @behaviour :application @doc false def stop(_state) do :ok end defoverridable [stop: 1] end end @type app :: atom @type key :: atom @type value :: term @type start_type :: :permanent | :transient | :temporary @doc """ Returns all key-value pairs for `app`. """ @spec get_all_env(app) :: [{key, value}] def get_all_env(app) do :application.get_all_env(app) end @doc """ Returns the value for `key` in `app`'s environment. If the configuration parameter does not exist, the function returns the `default` value. """ @spec get_env(app, key, value) :: value def get_env(app, key, default \\ nil) do :application.get_env(app, key, default) end @doc """ Returns the value for `key` in `app`'s environment in a tuple. If the configuration parameter does not exist, the function returns `:error`. """ @spec fetch_env(app, key) :: {:ok, value} | :error def fetch_env(app, key) do case :application.get_env(app, key) do {:ok, value} -> {:ok, value} :undefined -> :error end end @doc """ Returns the value for `key` in `app`'s environment. If the configuration parameter does not exist, raises `ArgumentError`. """ @spec fetch_env!(app, key) :: value | no_return def fetch_env!(app, key) do case fetch_env(app, key) do {:ok, value} -> value :error -> raise ArgumentError, "application #{inspect app} is not loaded, " <> "or the configuration parameter #{inspect key} is not set" end end @doc """ Puts the `value` in `key` for the given `app`. ## Options * `:timeout` - the timeout for the change (defaults to 5000ms) * `:persistent` - persists the given value on application load and reloads If `put_env/4` is called before the application is loaded, the application environment values specified in the `.app` file will override the ones previously set. The persistent option can be set to `true` when there is a need to guarantee parameters set with this function will not be overridden by the ones defined in the application resource file on load. This means persistent values will stick after the application is loaded and also on application reload. """ @spec put_env(app, key, value, [timeout: timeout, persistent: boolean]) :: :ok def put_env(app, key, value, opts \\ []) do :application.set_env(app, key, value, opts) end @doc """ Deletes the `key` from the given `app` environment. See `put_env/4` for a description of the options. """ @spec delete_env(app, key, [timeout: timeout, persistent: boolean]) :: :ok def delete_env(app, key, opts \\ []) do :application.unset_env(app, key, opts) end @doc """ Ensures the given `app` is started. Same as `start/2` but returns `:ok` if the application was already started. This is useful in scripts and in test setup, where test applications need to be explicitly started: :ok = Application.ensure_started(:my_test_dep) """ @spec ensure_started(app, start_type) :: :ok | {:error, term} def ensure_started(app, type \\ :temporary) when is_atom(app) do :application.ensure_started(app, type) end @doc """ Ensures the given `app` and its applications are started. Same as `start/2` but also starts the applications listed under `:applications` in the `.app` file in case they were not previously started. """ @spec ensure_all_started(app, start_type) :: {:ok, [app]} | {:error, {app, term}} def ensure_all_started(app, type \\ :temporary) when is_atom(app) do :application.ensure_all_started(app, type) end @doc """ Starts the given `app`. If the `app` is not loaded, the application will first be loaded using `load/1`. Any included application, defined in the `:included_applications` key of the `.app` file will also be loaded, but they won't be started. Furthermore, all applications listed in the `:applications` key must be explicitly started before this application is. If not, `{:error, {:not_started, app}}` is returned, where `app` is the name of the missing application. In case you want to automatically load **and start** all of `app`'s dependencies, see `ensure_all_started/2`. The `type` argument specifies the type of the application: * `:permanent` - if `app` terminates, all other applications and the entire node are also terminated. * `:transient` - if `app` terminates with `:normal` reason, it is reported but no other applications are terminated. If a transient application terminates abnormally, all other applications and the entire node are also terminated. * `:temporary` - if `app` terminates, it is reported but no other applications are terminated (the default). Note that it is always possible to stop an application explicitly by calling `stop/1`. Regardless of the type of the application, no other applications will be affected. Note also that the `:transient` type is of little practical use, since when a supervision tree terminates, the reason is set to `:shutdown`, not `:normal`. """ @spec start(app, start_type) :: :ok | {:error, term} def start(app, type \\ :temporary) when is_atom(app) do :application.start(app, type) end @doc """ Stops the given `app`. When stopped, the application is still loaded. """ @spec stop(app) :: :ok | {:error, term} def stop(app) do :application.stop(app) end @doc """ Loads the given `app`. In order to be loaded, an `.app` file must be in the load paths. All `:included_applications` will also be loaded. Loading the application does not start it nor load its modules, but it does load its environment. """ @spec load(app) :: :ok | {:error, term} def load(app) when is_atom(app) do :application.load(app) end @doc """ Unloads the given `app`. It will also unload all `:included_applications`. Note that the function does not purge the application modules. """ @spec unload(app) :: :ok | {:error, term} def unload(app) when is_atom(app) do :application.unload(app) end @doc """ Gets the directory for app. This information is returned based on the code path. Here is an example: File.mkdir_p!("foo/ebin") Code.prepend_path("foo/ebin") Application.app_dir(:foo) #=> "foo" Even though the directory is empty and there is no `.app` file it is considered the application directory based on the name "foo/ebin". The name may contain a dash `-` which is considered to be the app version and it is removed for the lookup purposes: File.mkdir_p!("bar-123/ebin") Code.prepend_path("bar-123/ebin") Application.app_dir(:bar) #=> "bar-123" For more information on code paths, check the `Code` module in Elixir and also Erlang's `:code` module. """ @spec app_dir(app) :: String.t def app_dir(app) when is_atom(app) do case :code.lib_dir(app) do lib when is_list(lib) -> IO.chardata_to_string(lib) {:error, :bad_name} -> raise ArgumentError, "unknown application: #{inspect app}" end end @doc """ Returns the given path inside `app_dir/1`. """ @spec app_dir(app, String.t) :: String.t def app_dir(app, path) when is_binary(path) do Path.join(app_dir(app), path) end @doc """ Formats the error reason returned by `start/2`, `ensure_started/2`, `stop/1`, `load/1` and `unload/1`, returns a string. """ @spec format_error(any) :: String.t def format_error(reason) do try do impl_format_error(reason) catch # A user could create an error that looks like a builtin one # causing an error. :error, _ -> inspect(reason) end end # exit(:normal) call is special cased, undo the special case. defp impl_format_error({{:EXIT, :normal}, {mod, :start, args}}) do Exception.format_exit({:normal, {mod, :start, args}}) end # {:error, reason} return value defp impl_format_error({reason, {mod, :start, args}}) do Exception.format_mfa(mod, :start, args) <> " returned an error: " <> Exception.format_exit(reason) end # error or exit(reason) call, use exit reason as reason. defp impl_format_error({:bad_return, {{mod, :start, args}, {:EXIT, reason}}}) do Exception.format_exit({reason, {mod, :start, args}}) end # bad return value defp impl_format_error({:bad_return, {{mod, :start, args}, return}}) do Exception.format_mfa(mod, :start, args) <> " returned a bad value: " <> inspect(return) end defp impl_format_error({:already_started, app}) when is_atom(app) do "already started application #{app}" end defp impl_format_error({:not_started, app}) when is_atom(app) do "not started application #{app}" end defp impl_format_error({:bad_application, app}) do "bad application: #{inspect(app)}" end defp impl_format_error({:already_loaded, app}) when is_atom(app) do "already loaded application #{app}" end defp impl_format_error({:not_loaded, app}) when is_atom(app) do "not loaded application #{app}" end defp impl_format_error({:invalid_restart_type, restart}) do "invalid application restart type: #{inspect(restart)}" end defp impl_format_error({:invalid_name, name}) do "invalid application name: #{inspect(name)}" end defp impl_format_error({:invalid_options, opts}) do "invalid application options: #{inspect(opts)}" end defp impl_format_error({:badstartspec, spec}) do "bad application start specs: #{inspect(spec)}" end defp impl_format_error({'no such file or directory', file}) do "could not find application file: #{file}" end defp impl_format_error(reason) do Exception.format_exit(reason) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/atom.ex000066400000000000000000000011671254730255300212300ustar00rootroot00000000000000defmodule Atom do @moduledoc """ Convenience functions for working with atoms. See also `Kernel.is_atom/1`. """ @doc """ Converts an atom to a string. Inlined by the compiler. ## Examples iex> Atom.to_string(:foo) "foo" """ @spec to_string(atom) :: String.t def to_string(atom) do :erlang.atom_to_binary(atom, :utf8) end @doc """ Converts an atom to a char list. Inlined by the compiler. ## Examples iex> Atom.to_char_list(:"An atom") 'An atom' """ @spec to_char_list(atom) :: char_list def to_char_list(atom) do :erlang.atom_to_list(atom) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/base.ex000066400000000000000000000503011254730255300211740ustar00rootroot00000000000000defmodule Base do import Bitwise @moduledoc """ This module provides data encoding and decoding functions according to [RFC 4648](http://tools.ietf.org/html/rfc4648). This document defines the commonly used base 16, base 32, and base 64 encoding schemes. ## Base 16 alphabet | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| | 0| 0| 4| 4| 8| 8| 12| C| | 1| 1| 5| 5| 9| 9| 13| D| | 2| 2| 6| 6| 10| A| 14| E| | 3| 3| 7| 7| 11| B| 15| F| ## Base 32 alphabet | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| | 0| A| 9| J| 18| S| 27| 3| | 1| B| 10| K| 19| T| 28| 4| | 2| C| 11| L| 20| U| 29| 5| | 3| D| 12| M| 21| V| 30| 6| | 4| E| 13| N| 22| W| 31| 7| | 5| F| 14| O| 23| X| | | | 6| G| 15| P| 24| Y| (pad)| =| | 7| H| 16| Q| 25| Z| | | | 8| I| 17| R| 26| 2| | | ## Base 32 (extended hex) alphabet | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| | 0| 0| 9| 9| 18| I| 27| R| | 1| 1| 10| A| 19| J| 28| S| | 2| 2| 11| B| 20| K| 29| T| | 3| 3| 12| C| 21| L| 30| U| | 4| 4| 13| D| 22| M| 31| V| | 5| 5| 14| E| 23| N| | | | 6| 6| 15| F| 24| O| (pad)| =| | 7| 7| 16| G| 25| P| | | | 8| 8| 17| H| 26| Q| | | ## Base 64 alphabet | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| | 0| A| 17| R| 34| i| 51| z| | 1| B| 18| S| 35| j| 52| 0| | 2| C| 19| T| 36| k| 53| 1| | 3| D| 20| U| 37| l| 54| 2| | 4| E| 21| V| 38| m| 55| 3| | 5| F| 22| W| 39| n| 56| 4| | 6| G| 23| X| 40| o| 57| 5| | 7| H| 24| Y| 41| p| 58| 6| | 8| I| 25| Z| 42| q| 59| 7| | 9| J| 26| a| 43| r| 60| 8| | 10| K| 27| b| 44| s| 61| 9| | 11| L| 28| c| 45| t| 62| +| | 12| M| 29| d| 46| u| 63| /| | 13| N| 30| e| 47| v| | | | 14| O| 31| f| 48| w| (pad)| =| | 15| P| 32| g| 49| x| | | | 16| Q| 33| h| 50| y| | | ## Base 64 (URL and filename safe) alphabet | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| | 0| A| 17| R| 34| i| 51| z| | 1| B| 18| S| 35| j| 52| 0| | 2| C| 19| T| 36| k| 53| 1| | 3| D| 20| U| 37| l| 54| 2| | 4| E| 21| V| 38| m| 55| 3| | 5| F| 22| W| 39| n| 56| 4| | 6| G| 23| X| 40| o| 57| 5| | 7| H| 24| Y| 41| p| 58| 6| | 8| I| 25| Z| 42| q| 59| 7| | 9| J| 26| a| 43| r| 60| 8| | 10| K| 27| b| 44| s| 61| 9| | 11| L| 28| c| 45| t| 62| -| | 12| M| 29| d| 46| u| 63| _| | 13| N| 30| e| 47| v| | | | 14| O| 31| f| 48| w| (pad)| =| | 15| P| 32| g| 49| x| | | | 16| Q| 33| h| 50| y| | | """ b16_alphabet = Enum.with_index '0123456789ABCDEF' b64_alphabet = Enum.with_index 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' b64url_alphabet = Enum.with_index 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' b32_alphabet = Enum.with_index 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' b32hex_alphabet = Enum.with_index '0123456789ABCDEFGHIJKLMNOPQRSTUV' Enum.each [ {:enc16, :dec16, b16_alphabet}, {:enc64, :dec64, b64_alphabet}, {:enc32, :dec32, b32_alphabet}, {:enc64url, :dec64url, b64url_alphabet}, {:enc32hex, :dec32hex, b32hex_alphabet} ], fn({enc, dec, alphabet}) -> for {encoding, value} <- alphabet do defp unquote(enc)(unquote(value)), do: unquote(encoding) defp unquote(dec)(unquote(encoding)), do: unquote(value) end defp unquote(dec)(c) do raise ArgumentError, "non-alphabet digit found: #{<>}" end end defp encode_case(:upper, func), do: func defp encode_case(:lower, func), do: &to_lower(func.(&1)) defp decode_case(:upper, func), do: func defp decode_case(:lower, func), do: &func.(from_lower(&1)) defp decode_case(:mixed, func), do: &func.(from_mixed(&1)) defp to_lower(char) when char in ?A..?Z, do: char + (?a - ?A) defp to_lower(char), do: char defp from_lower(char) when char in ?a..?z, do: char - (?a - ?A) defp from_lower(char) when not char in ?A..?Z, do: char defp from_lower(char), do: raise(ArgumentError, "non-alphabet digit found: #{<>}") defp from_mixed(char) when char in ?a..?z, do: char - (?a - ?A) defp from_mixed(char), do: char @doc """ Encodes a binary string into a base 16 encoded string. Accepts an atom `:upper` (default) for encoding to upper case characters or `:lower` for lower case characters. ## Examples iex> Base.encode16("foobar") "666F6F626172" iex> Base.encode16("foobar", case: :lower) "666f6f626172" """ @spec encode16(binary) :: binary @spec encode16(binary, Keyword.t) :: binary def encode16(data, opts \\ []) when is_binary(data) do case = Keyword.get(opts, :case, :upper) do_encode16(data, encode_case(case, &enc16/1)) end @doc """ Decodes a base 16 encoded string into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. ## Examples iex> Base.decode16("666F6F626172") {:ok, "foobar"} iex> Base.decode16("666f6f626172", case: :lower) {:ok, "foobar"} iex> Base.decode16("666f6F626172", case: :mixed) {:ok, "foobar"} """ @spec decode16(binary) :: {:ok, binary} | :error @spec decode16(binary, Keyword.t) :: {:ok, binary} | :error def decode16(string, opts \\ []) when is_binary(string) do case = Keyword.get(opts, :case, :upper) {:ok, do_decode16(string, decode_case(case, &dec16/1))} rescue ArgumentError -> :error end @doc """ Decodes a base 16 encoded string into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. An `ArgumentError` exception is raised if the padding is incorrect or a non-alphabet character is present in the string. ## Examples iex> Base.decode16!("666F6F626172") "foobar" iex> Base.decode16!("666f6f626172", case: :lower) "foobar" iex> Base.decode16!("666f6F626172", case: :mixed) "foobar" """ @spec decode16!(binary) :: binary @spec decode16!(binary, Keyword.t) :: binary def decode16!(string, opts \\ []) when is_binary(string) do case = Keyword.get(opts, :case, :upper) do_decode16(string, decode_case(case, &dec16/1)) end @doc """ Encodes a binary string into a base 64 encoded string. ## Examples iex> Base.encode64("foobar") "Zm9vYmFy" """ @spec encode64(binary) :: binary def encode64(data) when is_binary(data) do do_encode64(data, &enc64/1) end @doc """ Decodes a base 64 encoded string into a binary string. ## Examples iex> Base.decode64("Zm9vYmFy") {:ok, "foobar"} """ @spec decode64(binary) :: {:ok, binary} | :error def decode64(string) when is_binary(string) do {:ok, do_decode64(string, &dec64/1)} rescue ArgumentError -> :error end @doc """ Decodes a base 64 encoded string into a binary string. The following alphabet is used both for encoding and decoding: An `ArgumentError` exception is raised if the padding is incorrect or a non-alphabet character is present in the string. ## Examples iex> Base.decode64!("Zm9vYmFy") "foobar" """ @spec decode64!(binary) :: binary def decode64!(string) when is_binary(string) do do_decode64(string, &dec64/1) end @doc """ Encodes a binary string into a base 64 encoded string with URL and filename safe alphabet. ## Examples iex> Base.url_encode64(<<255, 127, 254, 252>>) "_3_-_A==" """ @spec url_encode64(binary) :: binary def url_encode64(data) when is_binary(data) do do_encode64(data, &enc64url/1) end @doc """ Decodes a base 64 encoded string with URL and filename safe alphabet into a binary string. ## Examples iex> Base.url_decode64("_3_-_A==") {:ok, <<255, 127, 254, 252>>} """ @spec url_decode64(binary) :: {:ok, binary} | :error def url_decode64(string) when is_binary(string) do {:ok, do_decode64(string, &dec64url/1)} rescue ArgumentError -> :error end @doc """ Decodes a base 64 encoded string with URL and filename safe alphabet into a binary string. An `ArgumentError` exception is raised if the padding is incorrect or a non-alphabet character is present in the string. ## Examples iex> Base.url_decode64!("_3_-_A==") <<255, 127, 254, 252>> """ @spec url_decode64!(binary) :: binary def url_decode64!(string) when is_binary(string) do do_decode64(string, &dec64url/1) end @doc """ Encodes a binary string into a base 32 encoded string. Accepts an atom `:upper` (default) for encoding to upper case characters or `:lower` for lower case characters. ## Examples iex> Base.encode32("foobar") "MZXW6YTBOI======" iex> Base.encode32("foobar", case: :lower) "mzxw6ytboi======" """ @spec encode32(binary) :: binary @spec encode32(binary, Keyword.t) :: binary def encode32(data, opts \\ []) when is_binary(data) do case = Keyword.get(opts, :case, :upper) do_encode32(data, encode_case(case, &enc32/1)) end @doc """ Decodes a base 32 encoded string into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. ## Examples iex> Base.decode32("MZXW6YTBOI======") {:ok, "foobar"} iex> Base.decode32("mzxw6ytboi======", case: :lower) {:ok, "foobar"} iex> Base.decode32("mzXW6ytBOi======", case: :mixed) {:ok, "foobar"} """ @spec decode32(binary) :: {:ok, binary} | :error @spec decode32(binary, Keyword.t) :: {:ok, binary} | :error def decode32(string, opts \\ []) do case = Keyword.get(opts, :case, :upper) {:ok, do_decode32(string, decode_case(case, &dec32/1))} rescue ArgumentError -> :error end @doc """ Decodes a base 32 encoded string into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. An `ArgumentError` exception is raised if the padding is incorrect or a non-alphabet character is present in the string. ## Examples iex> Base.decode32!("MZXW6YTBOI======") "foobar" iex> Base.decode32!("mzxw6ytboi======", case: :lower) "foobar" iex> Base.decode32!("mzXW6ytBOi======", case: :mixed) "foobar" """ @spec decode32!(binary) :: binary @spec decode32!(binary, Keyword.t) :: binary def decode32!(string, opts \\ []) do case = Keyword.get(opts, :case, :upper) do_decode32(string, decode_case(case, &dec32/1)) end @doc """ Encodes a binary string into a base 32 encoded string with an extended hexadecimal alphabet. Accepts an atom `:upper` (default) for encoding to upper case characters or `:lower` for lower case characters. ## Examples iex> Base.hex_encode32("foobar") "CPNMUOJ1E8======" iex> Base.hex_encode32("foobar", case: :lower) "cpnmuoj1e8======" """ @spec hex_encode32(binary) :: binary @spec hex_encode32(binary, Keyword.t) :: binary def hex_encode32(data, opts \\ []) when is_binary(data) do case = Keyword.get(opts, :case, :upper) do_encode32(data, encode_case(case, &enc32hex/1)) end @doc """ Decodes a base 32 encoded string with extended hexadecimal alphabet into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. ## Examples iex> Base.hex_decode32("CPNMUOJ1E8======") {:ok, "foobar"} iex> Base.hex_decode32("cpnmuoj1e8======", case: :lower) {:ok, "foobar"} iex> Base.hex_decode32("cpnMuOJ1E8======", case: :mixed) {:ok, "foobar"} """ @spec hex_decode32(binary) :: {:ok, binary} | :error @spec hex_decode32(binary, Keyword.t) :: {:ok, binary} | :error def hex_decode32(string, opts \\ []) when is_binary(string) do case = Keyword.get(opts, :case, :upper) {:ok, do_decode32(string, decode_case(case, &dec32hex/1))} rescue ArgumentError -> :error end @doc """ Decodes a base 32 encoded string with extended hexadecimal alphabet into a binary string. Accepts an atom `:upper` (default) for decoding from upper case characters or `:lower` for lower case characters. `:mixed` can be given for mixed case characters. An `ArgumentError` exception is raised if the padding is incorrect or a non-alphabet character is present in the string. ## Examples iex> Base.hex_decode32!("CPNMUOJ1E8======") "foobar" iex> Base.hex_decode32!("cpnmuoj1e8======", case: :lower) "foobar" iex> Base.hex_decode32!("cpnMuOJ1E8======", case: :mixed) "foobar" """ @spec hex_decode32!(binary) :: binary @spec hex_decode32!(binary, Keyword.t) :: binary def hex_decode32!(string, opts \\ []) when is_binary(string) do case = Keyword.get(opts, :case, :upper) do_decode32(string, decode_case(case, &dec32hex/1)) end defp do_encode16(<<>>, _), do: <<>> defp do_encode16(data, enc) do for <>, into: <<>>, do: <> end defp do_decode16(<<>>, _), do: <<>> defp do_decode16(string, dec) when rem(byte_size(string), 2) == 0 do for <>, into: <<>> do <> end end defp do_decode16(_, _) do raise ArgumentError, "odd-length string" end defp do_encode64(<<>>, _), do: <<>> defp do_encode64(data, enc) do split = 3 * div(byte_size(data), 3) <> = data main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <<>> -> main end end defp do_decode64(<<>>, _), do: <<>> defp do_decode64(string, dec) when rem(byte_size(string), 4) == 0 do split = byte_size(string) - 4 <> = string main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <> -> <> <<>> -> main end end defp do_decode64(_, _) do raise ArgumentError, "incorrect padding" end defp do_encode32(<<>>, _), do: <<>> defp do_encode32(data, enc) do split = 5 * div(byte_size(data), 5) <> = data main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <> -> <> <> -> <> <<>> -> main end end defp do_decode32(<<>>, _), do: <<>> defp do_decode32(string, dec) when rem(byte_size(string), 8) == 0 do split = byte_size(string) - 8 <> = string main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <> -> <> <> -> <> <> -> <> <<>> -> main end end defp do_decode32(_, _) do raise ArgumentError, "incorrect padding" end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/behaviour.ex000066400000000000000000000100731254730255300222500ustar00rootroot00000000000000defmodule Behaviour do @moduledoc """ Utilities for defining behaviour interfaces. Behaviours can be referenced by other modules to ensure they implement required callbacks. For example, you can specify the `URI.Parser` behaviour as follows: defmodule URI.Parser do use Behaviour @doc "Parses the given URL" defcallback parse(uri_info :: URI.t) :: URI.t @doc "Defines a default port" defcallback default_port() :: integer end And then a module may use it as: defmodule URI.HTTP do @behaviour URI.Parser def default_port(), do: 80 def parse(info), do: info end If the behaviour changes or `URI.HTTP` does not implement one of the callbacks, a warning will be raised. ## Implementation Since Erlang R15, behaviours must be defined via `@callback` attributes. `defcallback` is a simple mechanism that defines the `@callback` attribute according to the given type specification. `defcallback` allows documentation to be created for the callback and defines a custom function signature. The callbacks and their documentation can be retrieved via the `__behaviour__` callback function. """ @doc """ Defines a function callback according to the given type specification. """ defmacro defcallback(spec) do do_defcallback(split_spec(spec, quote(do: term)), __CALLER__) end @doc """ Defines a macro callback according to the given type specification. """ defmacro defmacrocallback(spec) do do_defmacrocallback(split_spec(spec, quote(do: Macro.t)), __CALLER__) end defp split_spec({:when, _, [{:::, _, [spec, return]}, guard]}, _default) do {spec, return, guard} end defp split_spec({:when, _, [spec, guard]}, default) do {spec, default, guard} end defp split_spec({:::, _, [spec, return]}, _default) do {spec, return, []} end defp split_spec(spec, default) do {spec, default, []} end defp do_defcallback({spec, return, guards}, caller) do case Macro.decompose_call(spec) do {name, args} -> do_callback(:def, name, args, name, length(args), args, return, guards, caller) _ -> raise ArgumentError, "invalid syntax in defcallback #{Macro.to_string(spec)}" end end defp do_defmacrocallback({spec, return, guards}, caller) do case Macro.decompose_call(spec) do {name, args} -> do_callback(:defmacro, :"MACRO-#{name}", [quote(do: env :: Macro.Env.t)|args], name, length(args), args, return, guards, caller) _ -> raise ArgumentError, "invalid syntax in defmacrocallback #{Macro.to_string(spec)}" end end defp do_callback(kind, name, args, docs_name, docs_arity, _docs_args, return, guards, caller) do :lists.foreach fn {:::, _, [left, right]} -> ensure_not_default(left) ensure_not_default(right) left other -> ensure_not_default(other) other end, args quote do @callback unquote(name)(unquote_splicing(args)) :: unquote(return) when unquote(guards) Behaviour.store_docs(__MODULE__, unquote(caller.line), unquote(kind), unquote(docs_name), unquote(docs_arity)) end end defp ensure_not_default({:\\, _, [_, _]}) do raise ArgumentError, "default arguments \\\\ not supported in defcallback/defmacrocallback" end defp ensure_not_default(_), do: :ok @doc false def store_docs(module, line, kind, name, arity) do doc = Module.get_attribute module, :doc Module.delete_attribute module, :doc Module.put_attribute module, :behaviour_docs, {{name, arity}, line, kind, doc} end @doc false defmacro __using__(_) do quote do Module.register_attribute(__MODULE__, :behaviour_docs, accumulate: true) # TODO: Deprecate by 1.2 # TODO: Remove by 2.0 @doc false def __behaviour__(:callbacks) do __MODULE__.behaviour_info(:callbacks) end def __behaviour__(:docs) do Code.get_docs(__MODULE__, :behaviour_docs) end import unquote(__MODULE__) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/bitwise.ex000066400000000000000000000075341254730255300217420ustar00rootroot00000000000000defmodule Bitwise do @moduledoc """ This module provides macro-based operators that perform calculations on (sets of) bits. In general, you should `use` the Bitwise module as a whole: iex> use Bitwise iex> bnot 1 -2 iex> 1 &&& 1 1 Alternatively, you can include or skip selected operators: iex> use Bitwise, only_operators: true iex> 1 &&& 1 1 These macros can be used in guards: iex> use Bitwise iex> odd? = fn(int) when band(int, 1) == 1 -> true; (_) -> false end iex> odd?.(1) true """ @doc """ Allows a developer to `use` this module in their programs with the following options: * `:only_operators` - include only operators * `:skip_operators` - skip operators """ defmacro __using__(options) do except = cond do Keyword.get(options, :only_operators) -> [bnot: 1, band: 2, bor: 2, bxor: 2, bsl: 2, bsr: 2] Keyword.get(options, :skip_operators) -> [~~~: 1, &&&: 2, |||: 2, ^^^: 2, <<<: 2, >>>: 2] true -> [] end quote do import Bitwise, except: unquote(except) end end @doc """ Calculates the bitwise NOT of its argument. iex> bnot(2) -3 iex> bnot(2) &&& 3 1 """ defmacro bnot(expr) do quote do: :erlang.bnot(unquote(expr)) end @doc """ Prefix (unary) operator; calculates the bitwise NOT of its argument. iex> ~~~2 -3 iex> ~~~2 &&& 3 1 """ defmacro ~~~expr do quote do: :erlang.bnot(unquote(expr)) end @doc """ Calculates the bitwise AND of its arguments. iex> band(9, 3) 1 """ defmacro band(left, right) do quote do: :erlang.band(unquote(left), unquote(right)) end @doc """ Infix operator; calculates the bitwise AND of its arguments. iex> 9 &&& 3 1 """ defmacro left &&& right do quote do: :erlang.band(unquote(left), unquote(right)) end @doc """ Calculates the bitwise OR of its arguments. iex> bor(9, 3) 11 """ defmacro bor(left, right) do quote do: :erlang.bor(unquote(left), unquote(right)) end @doc """ Infix operator; calculates the bitwise OR of its arguments. iex> 9 ||| 3 11 """ defmacro left ||| right do quote do: :erlang.bor(unquote(left), unquote(right)) end @doc """ Calculates the bitwise XOR of its arguments. iex> bxor(9, 3) 10 """ defmacro bxor(left, right) do quote do: :erlang.bxor(unquote(left), unquote(right)) end @doc """ Infix operator; calculates the bitwise XOR of its arguments. iex> 9 ^^^ 3 10 """ defmacro left ^^^ right do quote do: :erlang.bxor(unquote(left), unquote(right)) end @doc """ Calculates the result of an arithmetic left bitshift. iex> bsl(1, 2) 4 iex> bsl(1, -2) 0 iex> bsl(-1, 2) -4 iex> bsl(-1, -2) -1 """ defmacro bsl(left, right) do quote do: :erlang.bsl(unquote(left), unquote(right)) end @doc """ Infix operator; calculates the result of an arithmetic left bitshift. iex> 1 <<< 2 4 iex> 1 <<< -2 0 iex> -1 <<< 2 -4 iex> -1 <<< -2 -1 """ defmacro left <<< right do quote do: :erlang.bsl(unquote(left), unquote(right)) end @doc """ Calculates the result of an arithmetic right bitshift. iex> bsr(1, 2) 0 iex> bsr(1, -2) 4 iex> bsr(-1, 2) -1 iex> bsr(-1, -2) -4 """ defmacro bsr(left, right) do quote do: :erlang.bsr(unquote(left), unquote(right)) end @doc """ Infix operator; calculates the result of an arithmetic left bitshift. iex> 1 >>> 2 0 iex> 1 >>> -2 4 iex> -1 >>> 2 -1 iex> -1 >>> -2 -4 """ defmacro left >>> right do quote do: :erlang.bsr(unquote(left), unquote(right)) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/code.ex000066400000000000000000000467761254730255300212210ustar00rootroot00000000000000defmodule Code do @moduledoc """ Utilities for managing code compilation, code evaluation and code loading. This module complements [Erlang's code module](http://www.erlang.org/doc/man/code.html) to add behaviour which is specific to Elixir. Almost all of the functions in this module have global side effects on the behaviour of Elixir. """ @doc """ Lists all loaded files. ## Examples Code.require_file("../eex/test/eex_test.exs") List.first(Code.loaded_files) =~ "eex_test.exs" #=> true """ def loaded_files do :elixir_code_server.call :loaded end @doc """ Removes files from the loaded files list. The modules defined in the file are not removed; calling this function only removes them from the list, allowing them to be required again. ## Examples # Load EEx test code, unload file, check for functions still available Code.load_file("../eex/test/eex_test.exs") Code.unload_files(Code.loaded_files) function_exported?(EExTest.Compiled, :before_compile, 0) #=> true """ def unload_files(files) do :elixir_code_server.cast {:unload_files, files} end @doc """ Appends a path to the end of the Erlang VM code path list. This is the list of directories the Erlang VM uses for finding module code. The path is expanded with `Path.expand/1` before being appended. If this path does not exist, an error is returned. ## Examples Code.append_path(".") #=> true Code.append_path("/does_not_exist") #=> {:error, :bad_directory} """ def append_path(path) do :code.add_pathz(to_char_list(Path.expand path)) end @doc """ Prepends a path to the begining of the Erlang VM code path list. This is the list of directories the Erlang VM uses for finding module code. The path is expanded with `Path.expand/1` before being prepended. If this path does not exist, an error is returned. ## Examples Code.prepend_path(".") #=> true Code.prepend_path("/does_not_exist") #=> {:error, :bad_directory} """ def prepend_path(path) do :code.add_patha(to_char_list(Path.expand path)) end @doc """ Deletes a path from the Erlang VM code path list. This is the list of directories the Erlang VM uses for finding module code. The path is expanded with `Path.expand/1` before being deleted. If the path does not exist it returns false. ## Examples Code.prepend_path(".") Code.delete_path(".") #=> true Code.delete_path("/does_not_exist") #=> false """ def delete_path(path) do :code.del_path(to_char_list(Path.expand path)) end @doc """ Evaluates the contents given by `string`. The `binding` argument is a keyword list of variable bindings. The `opts` argument is a keyword list of environment options. Those options can be: * `:file` - the file to be considered in the evaluation * `:line` - the line on which the script starts Additionally, the following scope values can be configured: * `:aliases` - a list of tuples with the alias and its target * `:requires` - a list of modules required * `:functions` - a list of tuples where the first element is a module and the second a list of imported function names and arity; the list of function names and arity must be sorted * `:macros` - a list of tuples where the first element is a module and the second a list of imported macro names and arity; the list of function names and arity must be sorted Notice that setting any of the values above overrides Elixir's default values. For example, setting `:requires` to `[]`, will no longer automatically require the `Kernel` module; in the same way setting `:macros` will no longer auto-import `Kernel` macros like `if`, `case`, etc. Returns a tuple of the form `{value, binding}`, where `value` is the value returned from evaluating `string`. If an error occurs while evaluating `string` an exception will be raised. `binding` is a keyword list with the value of all variable bindings after evaluating `string`. The binding key is usually an atom, but it may be a tuple for variables defined in a different context. ## Examples iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line) {3, [a: 1, b: 2]} iex> Code.eval_string("c = a + b", [a: 1, b: 2], __ENV__) {3, [a: 1, b: 2, c: 3]} iex> Code.eval_string("a = a + b", [a: 1, b: 2]) {3, [a: 3, b: 2]} For convenience, you can pass `__ENV__` as the `opts` argument and all imports, requires and aliases defined in the current environment will be automatically carried over: iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__) {3, [a: 1, b: 2]} """ def eval_string(string, binding \\ [], opts \\ []) def eval_string(string, binding, %Macro.Env{} = env) do {value, binding, _env, _scope} = :elixir.eval to_char_list(string), binding, Map.to_list(env) {value, binding} end def eval_string(string, binding, opts) when is_list(opts) do validate_eval_opts(opts) {value, binding, _env, _scope} = :elixir.eval to_char_list(string), binding, opts {value, binding} end @doc """ Evaluates the quoted contents. See `eval_string/3` for a description of arguments and return values. ## Examples iex> contents = quote(do: var!(a) + var!(b)) iex> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line) {3, [a: 1, b: 2]} For convenience, you can pass `__ENV__` as the `opts` argument and all options will be automatically extracted from the current environment: iex> contents = quote(do: var!(a) + var!(b)) iex> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__) {3, [a: 1, b: 2]} """ def eval_quoted(quoted, binding \\ [], opts \\ []) def eval_quoted(quoted, binding, %Macro.Env{} = env) do {value, binding, _env, _scope} = :elixir.eval_quoted quoted, binding, Map.to_list(env) {value, binding} end def eval_quoted(quoted, binding, opts) when is_list(opts) do validate_eval_opts(opts) {value, binding, _env, _scope} = :elixir.eval_quoted quoted, binding, opts {value, binding} end defp validate_eval_opts(opts) do if f = opts[:functions], do: validate_imports(:functions, f) if m = opts[:macros], do: validate_imports(:macros, m) if a = opts[:aliases], do: validate_aliases(:aliases, a) if r = opts[:requires], do: validate_requires(:requires, r) end defp validate_requires(kind, requires) do valid = is_list(requires) and Enum.all?(requires, &is_atom(&1)) unless valid do raise ArgumentError, "expected :#{kind} option given to eval in the format: [module]" end end defp validate_aliases(kind, aliases) do valid = is_list(aliases) and Enum.all?(aliases, fn {k, v} -> is_atom(k) and is_atom(v) end) unless valid do raise ArgumentError, "expected :#{kind} option given to eval in the format: [{module, module}]" end end defp validate_imports(kind, imports) do valid = is_list(imports) and Enum.all?(imports, fn {k, v} -> is_atom(k) and is_list(v) and Enum.all?(v, fn {name, arity} -> is_atom(name) and is_integer(arity) end) end) unless valid do raise ArgumentError, "expected :#{kind} option given to eval in the format: [{module, [{name, arity}]}]" end end @doc """ Converts the given string to its quoted form. Returns `{:ok, quoted_form}` if it succeeds, `{:error, {line, error, token}}` otherwise. ## Options * `:file` - the filename to be used in stacktraces and the file reported in the `__ENV__` variable * `:line` - the line reported in the `__ENV__` variable * `:existing_atoms_only` - when `true`, raises an error when non-existing atoms are found by the tokenizer ## Macro.to_string/2 The opposite of converting a string to its quoted form is `Macro.to_string/2`, which converts a quoted form to a string/binary representation. """ def string_to_quoted(string, opts \\ []) when is_list(opts) do file = Keyword.get opts, :file, "nofile" line = Keyword.get opts, :line, 1 :elixir.string_to_quoted(to_char_list(string), line, file, opts) end @doc """ Converts the given string to its quoted form. It returns the ast if it succeeds, raises an exception otherwise. The exception is a `TokenMissingError` in case a token is missing (usually because the expression is incomplete), `SyntaxError` otherwise. Check `string_to_quoted/2` for options information. """ def string_to_quoted!(string, opts \\ []) when is_list(opts) do file = Keyword.get opts, :file, "nofile" line = Keyword.get opts, :line, 1 :elixir.string_to_quoted!(to_char_list(string), line, file, opts) end @doc """ Evals the given file. Accepts `relative_to` as an argument to tell where the file is located. While `load_file` loads a file and returns the loaded modules and their byte code, `eval_file` simply evaluates the file contents and returns the evaluation result and its bindings. """ def eval_file(file, relative_to \\ nil) do file = find_file(file, relative_to) eval_string File.read!(file), [], [file: file, line: 1] end @doc """ Loads the given file. Accepts `relative_to` as an argument to tell where the file is located. If the file was already required/loaded, loads it again. It returns a list of tuples `{ModuleName, <>}`, one tuple for each module defined in the file. Notice that if `load_file` is invoked by different processes concurrently, the target file will be loaded concurrently many times. Check `require_file/2` if you don't want a file to be loaded concurrently. ## Examples Code.load_file("eex_test.exs","../eex/test") |> List.first #=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>} """ def load_file(file, relative_to \\ nil) when is_binary(file) do file = find_file(file, relative_to) :elixir_code_server.call {:acquire, file} loaded = :elixir_compiler.file file :elixir_code_server.cast {:loaded, file} loaded end @doc """ Requires the given `file`. Accepts `relative_to` as an argument to tell where the file is located. The return value is the same as that of `load_file/2`. If the file was already required/loaded, doesn't do anything and returns `nil`. Notice that if `require_file` is invoked by different processes concurrently, the first process to invoke `require_file` acquires a lock and the remaining ones will block until the file is available. I.e. if `require_file` is called N times with a given file, it will be loaded only once. The first process to call `require_file` will get the list of loaded modules, others will get `nil`. Check `load_file/2` if you want a file to be loaded multiple times. See also `unload_files/1` ## Examples If the code is already loaded, it returns nil: Code.require_file("eex_test.exs","../eex/test") #=> nil If the code is not already loaded, it returns the same as `load_file/2`: Code.require_file("eex_test.exs","../eex/test") |> List.first #=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>} """ def require_file(file, relative_to \\ nil) when is_binary(file) do file = find_file(file, relative_to) case :elixir_code_server.call({:acquire, file}) do :loaded -> nil {:queued, ref} -> receive do {:elixir_code_server, ^ref, :loaded} -> nil end :proceed -> loaded = :elixir_compiler.file file :elixir_code_server.cast {:loaded, file} loaded end end @doc """ Gets the compilation options from the code server. Check `compiler_options/1` for more information. ## Examples Code.compiler_options #=> [debug_info: true, docs: true, warnings_as_errors: false] """ def compiler_options do :elixir_config.get :compiler_options end @doc """ Returns a list with the available compiler options. See `Code.compiler_options/1` for more info. ## Examples Code.available_compiler_options #=> [:docs, :debug_info, :ignore_module_conflict, :warnings_as_errors] """ def available_compiler_options do [:docs, :debug_info, :ignore_module_conflict, :warnings_as_errors] end @doc """ Sets compilation options. These options are global since they are stored by Elixir's Code Server. Available options are: * `:docs` - when `true`, retain documentation in the compiled module, `true` by default * `:debug_info` - when `true`, retain debug information in the compiled module; this allows a developer to reconstruct the original source code, `false` by default * `:ignore_module_conflict` - when `true`, override modules that were already defined without raising errors, `false` by default * `:warnings_as_errors` - cause compilation to fail when warnings are generated It returns the new list of compiler options. ## Examples Code.compiler_options(debug_info: true) #=> [debug_info: true, docs: true, warnings_as_errors: false] """ def compiler_options(opts) do {opts, bad} = Keyword.split(opts, available_compiler_options) if bad != [] do bad = bad |> Keyword.keys |> Enum.join(", ") raise ArgumentError, message: "unknown compiler options: #{bad}" end update = &:orddict.merge(fn(_, _, value) -> value end, &1, opts) :elixir_config.update :compiler_options, update end @doc """ Compiles the given string. Returns a list of tuples where the first element is the module name and the second one is its byte code (as a binary). For compiling many files at once, check `Kernel.ParallelCompiler.files/2`. """ def compile_string(string, file \\ "nofile") when is_binary(file) do :elixir_compiler.string to_char_list(string), file end @doc """ Compiles the quoted expression. Returns a list of tuples where the first element is the module name and the second one is its byte code (as a binary). """ def compile_quoted(quoted, file \\ "nofile") when is_binary(file) do :elixir_compiler.quoted quoted, file end @doc """ Ensures the given module is loaded. If the module is already loaded, this works as no-op. If the module was not yet loaded, it tries to load it. If it succeeds loading the module, it returns `{:module, module}`. If not, returns `{:error, reason}` with the error reason. ## Code loading on the Erlang VM Erlang has two modes to load code: interactive and embedded. By default, the Erlang VM runs in interactive mode, where modules are loaded as needed. In embedded mode the opposite happens, as all modules need to be loaded upfront or explicitly. Therefore, this function is used to check if a module is loaded before using it and allows one to react accordingly. For example, the `URI` module uses this function to check if a specific parser exists for a given URI scheme. ## Code.ensure_compiled/1 Elixir also contains an `ensure_compiled/1` function that is a superset of `ensure_loaded/1`. Since Elixir's compilation happens in parallel, in some situations you may need to use a module that was not yet compiled, therefore it can't even be loaded. `ensure_compiled/1` halts the current process until the module we are depending on is available. In most cases, `ensure_loaded/1` is enough. `ensure_compiled/1` must be used in rare cases, usually involving macros that need to invoke a module for callback information. ## Examples iex> Code.ensure_loaded(Atom) {:module, Atom} iex> Code.ensure_loaded(DoesNotExist) {:error, :nofile} """ def ensure_loaded(module) when is_atom(module) do :code.ensure_loaded(module) end @doc """ Ensures the given module is loaded. Similar to `ensure_loaded/1`, but returns `true` if the module is already loaded or was successfully loaded. Returns `false` otherwise. ## Examples iex> Code.ensure_loaded?(Atom) true """ def ensure_loaded?(module) do match?({:module, ^module}, ensure_loaded(module)) end @doc """ Ensures the given module is compiled and loaded. If the module is already loaded, it works as no-op. If the module was not loaded yet, it checks if it needs to be compiled first and then tries to load it. If it succeeds loading the module, it returns `{:module, module}`. If not, returns `{:error, reason}` with the error reason. Check `ensure_loaded/1` for more information on module loading and when to use `ensure_loaded/1` or `ensure_compiled/1`. """ def ensure_compiled(module) when is_atom(module) do case :code.ensure_loaded(module) do {:error, :nofile} = error -> case :erlang.get(:elixir_ensure_compiled) do :undefined -> error _ -> try do module.__info__(:module) {:module, module} rescue UndefinedFunctionError -> error end end other -> other end end @doc """ Ensures the given module is compiled and loaded. Similar to `ensure_compiled/1`, but returns `true` if the module is already loaded or was successfully loaded and compiled. Returns `false` otherwise. """ def ensure_compiled?(module) do match?({:module, ^module}, ensure_compiled(module)) end @doc ~S""" Returns the docs for the given module. When given a module name, it finds its BEAM code and reads the docs from it. When given a path to a .beam file, it will load the docs directly from that file. The return value depends on the `kind` value: * `:docs` - list of all docstrings attached to functions and macros using the `@doc` attribute * `:moduledoc` - tuple `{, }` where `line` is the line on which module definition starts and `doc` is the string attached to the module using the `@moduledoc` attribute * `:behaviour_docs` - list of all docstrings attached to behaviour callbacks using the `@doc` attribute * `:all` - a keyword list with both `:docs` and `:moduledoc` ## Examples # Get the documentation for the first function listed iex> [fun|_] = Code.get_docs(Atom, :docs) |> Enum.sort() iex> {{_function, _arity}, _line, _kind, _signature, text} = fun iex> String.split(text, "\n") |> Enum.at(0) "Converts an atom to a char list." """ def get_docs(module, kind) when is_atom(module) do case :code.get_object_code(module) do {_module, bin, _beam_path} -> do_get_docs(bin, kind) :error -> nil end end def get_docs(binpath, kind) when is_binary(binpath) do do_get_docs(String.to_char_list(binpath), kind) end @docs_chunk 'ExDc' defp do_get_docs(bin_or_path, kind) do case :beam_lib.chunks(bin_or_path, [@docs_chunk]) do {:ok, {_module, [{@docs_chunk, bin}]}} -> lookup_docs(:erlang.binary_to_term(bin), kind) {:error, :beam_lib, {:missing_chunk, _, @docs_chunk}} -> nil end end defp lookup_docs({:elixir_docs_v1, docs}, kind), do: do_lookup_docs(docs, kind) # unsupported chunk version defp lookup_docs(_, _), do: nil @doc_sections [:docs, :moduledoc, :behaviour_docs] defp do_lookup_docs(docs, :all), do: docs defp do_lookup_docs(docs, kind) when kind in @doc_sections, do: Keyword.get(docs, kind) ## Helpers # Finds the file given the relative_to path. # # If the file is found, returns its path in binary, fails otherwise. defp find_file(file, relative_to) do file = if relative_to do Path.expand(file, relative_to) else Path.expand(file) end if File.regular?(file) do file else raise Code.LoadError, file: file end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/collectable.ex000066400000000000000000000044431254730255300225410ustar00rootroot00000000000000defprotocol Collectable do @moduledoc """ A protocol to traverse data structures. The `Enum.into/2` function uses this protocol to insert an enumerable into a collection: iex> Enum.into([a: 1, b: 2], %{}) %{a: 1, b: 2} ## Why Collectable? The `Enumerable` protocol is useful to take values out of a collection. In order to support a wide range of values, the functions provided by the `Enumerable` protocol do not keep shape. For example, passing a dictionary to `Enum.map/2` always returns a list. This design is intentional. `Enumerable` was designed to support infinite collections, resources and other structures with fixed shape. For example, it doesn't make sense to insert values into a range, as it has a fixed shape where just the range limits are stored. The `Collectable` module was designed to fill the gap left by the `Enumerable` protocol. `into/1` can be seen as the opposite of `Enumerable.reduce/3`. If `Enumerable` is about taking values out, `Collectable.into/1` is about collecting those values into a structure. """ @type command :: {:cont, term} | :done | :halt @doc """ Returns a function that collects values alongside the initial accumulation value. The returned function receives a collectable and injects a given value into it for every `{:cont, term}` instruction. `:done` is passed when no further values will be injected, useful for closing resources and normalizing values. A collectable must be returned on `:done`. If injection is suddenly interrupted, `:halt` is passed and it can return any value, as it won't be used. """ @spec into(t) :: {term, (term, command -> t | term)} def into(collectable) end defimpl Collectable, for: List do def into(original) do {[], fn list, {:cont, x} -> [x|list] list, :done -> original ++ :lists.reverse(list) _, :halt -> :ok end} end end defimpl Collectable, for: BitString do def into(original) do {original, fn acc, {:cont, x} when is_bitstring(x) -> [acc|x] acc, :done -> IO.iodata_to_binary(acc) _, :halt -> :ok end} end end defimpl Collectable, for: Map do def into(original) do {original, fn map, {:cont, {k, v}} -> :maps.put(k, v, map) map, :done -> map _, :halt -> :ok end} end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/dict.ex000066400000000000000000000553631254730255300212220ustar00rootroot00000000000000defmodule Dict do @moduledoc ~S""" This module specifies the Dict API expected to be implemented by different dictionaries. It also provides functions that redirect to the underlying Dict, allowing a developer to work with different Dict implementations using one API. To create a new dict, use the `new` functions defined by each dict type: HashDict.new #=> creates an empty HashDict In the examples below, `dict_impl` means a specific `Dict` implementation, for example `HashDict` or `Map`. ## Warning Do not use this module if you expect a certain `Dict` implementation. For example, if you are working with maps and you don't need polymorphism, it is preferrable to use the `Map` module instead of the `Dict` one. ## Protocols Besides implementing the functions in this module, all dictionaries are required to implement the `Access` protocol: iex> dict = dict_impl.new iex> dict = Dict.put(dict, :hello, :world) iex> dict[:hello] :world As well as the `Enumerable` and `Collectable` protocols. ## Match Dictionaries are required to implement all operations using the match (`===`) operator. ## Default implementation Default implementations for some functions in the `Dict` module are provided via `use Dict`. For example: defmodule MyDict do use Dict # implement required functions (see below) # override default implementations if optimization # is needed end The client module must contain the following functions: * `delete/2` * `fetch/2` * `put/3` * `reduce/3` * `size/1` All functions, except `reduce/3`, are required by the Dict behaviour. `reduce/3` must be implemented as per the Enumerable protocol. Based on these functions, `Dict` generates default implementations for the following functions: * `drop/2` * `equal?/2` * `fetch!/2` * `get/2` * `get/3` * `get_lazy/3` * `get_and_update/3` * `has_key?/2` * `keys/1` * `merge/2` * `merge/3` * `pop/2` * `pop/3` * `pop_lazy/3` * `put_new/3` * `put_new_lazy/3` * `split/2` * `take/2` * `to_list/1` * `update/4` * `update!/3` * `values/1` All of these functions are defined as overridable, so you can provide your own implementation if needed. Note you can also test your custom module via `Dict`'s doctests: defmodule MyDict do # ... end defmodule MyTests do use ExUnit.Case doctest Dict defp dict_impl, do: MyDict end """ use Behaviour @type key :: any @type value :: any @type t :: list | map defcallback new :: t defcallback delete(t, key) :: t defcallback drop(t, Enum.t) :: t defcallback equal?(t, t) :: boolean defcallback get(t, key) :: value defcallback get(t, key, value) :: value defcallback get_lazy(t, key, (() -> value)) :: value defcallback get_and_update(t, key, (value -> {value, value})) :: {value, t} defcallback fetch(t, key) :: {:ok, value} | :error defcallback fetch!(t, key) :: value | no_return defcallback has_key?(t, key) :: boolean defcallback keys(t) :: [key] defcallback merge(t, t) :: t defcallback merge(t, t, (key, value, value -> value)) :: t defcallback pop(t, key) :: {value, t} defcallback pop(t, key, value) :: {value, t} defcallback pop_lazy(t, key, (() -> value)) :: {value, t} defcallback put(t, key, value) :: t defcallback put_new(t, key, value) :: t defcallback put_new_lazy(t, key, (() -> value)) :: t defcallback size(t) :: non_neg_integer() defcallback split(t, Enum.t) :: {t, t} defcallback take(t, Enum.t) :: t defcallback to_list(t) :: list() defcallback update(t, key, value, (value -> value)) :: t defcallback update!(t, key, (value -> value)) :: t | no_return defcallback values(t) :: list(value) defmacro __using__(_) do # Use this import to guarantee proper code expansion import Kernel, except: [size: 1] quote do @behaviour Dict def get(dict, key, default \\ nil) do case fetch(dict, key) do {:ok, value} -> value :error -> default end end def get_lazy(dict, key, fun) when is_function(fun, 0) do case fetch(dict, key) do {:ok, value} -> value :error -> fun.() end end def get_and_update(dict, key, fun) do current_value = get(dict, key) {get, new_value} = fun.(current_value) {get, put(dict, key, new_value)} end def fetch!(dict, key) do case fetch(dict, key) do {:ok, value} -> value :error -> raise KeyError, key: key, term: dict end end def has_key?(dict, key) do match? {:ok, _}, fetch(dict, key) end def put_new(dict, key, value) do case has_key?(dict, key) do true -> dict false -> put(dict, key, value) end end def put_new_lazy(dict, key, fun) when is_function(fun, 0) do case has_key?(dict, key) do true -> dict false -> put(dict, key, fun.()) end end def drop(dict, keys) do Enum.reduce(keys, dict, &delete(&2, &1)) end def take(dict, keys) do Enum.reduce(keys, new, fn key, acc -> case fetch(dict, key) do {:ok, value} -> put(acc, key, value) :error -> acc end end) end def to_list(dict) do reduce(dict, {:cont, []}, fn kv, acc -> {:cont, [kv|acc]} end) |> elem(1) |> :lists.reverse end def keys(dict) do reduce(dict, {:cont, []}, fn {k, _}, acc -> {:cont, [k|acc]} end) |> elem(1) |> :lists.reverse end def values(dict) do reduce(dict, {:cont, []}, fn {_, v}, acc -> {:cont, [v|acc]} end) |> elem(1) |> :lists.reverse end def equal?(dict1, dict2) do # Use this import to avoid conflicts in the user code import Kernel, except: [size: 1] case size(dict1) == size(dict2) do false -> false true -> reduce(dict1, {:cont, true}, fn({k, v}, _acc) -> case fetch(dict2, k) do {:ok, ^v} -> {:cont, true} _ -> {:halt, false} end end) |> elem(1) end end def merge(dict1, dict2, fun \\ fn(_k, _v1, v2) -> v2 end) do # Use this import to avoid conflicts in the user code import Kernel, except: [size: 1] if size(dict1) < size(dict2) do reduce(dict1, {:cont, dict2}, fn {k, v1}, acc -> {:cont, update(acc, k, v1, &fun.(k, v1, &1))} end) else reduce(dict2, {:cont, dict1}, fn {k, v2}, acc -> {:cont, update(acc, k, v2, &fun.(k, &1, v2))} end) end |> elem(1) end def update(dict, key, initial, fun) do case fetch(dict, key) do {:ok, value} -> put(dict, key, fun.(value)) :error -> put(dict, key, initial) end end def update!(dict, key, fun) do case fetch(dict, key) do {:ok, value} -> put(dict, key, fun.(value)) :error -> raise KeyError, key: key, term: dict end end def pop(dict, key, default \\ nil) do case fetch(dict, key) do {:ok, value} -> {value, delete(dict, key)} :error -> {default, dict} end end def pop_lazy(dict, key, fun) when is_function(fun, 0) do case fetch(dict, key) do {:ok, value} -> {value, delete(dict, key)} :error -> {fun.(), dict} end end def split(dict, keys) do Enum.reduce(keys, {new, dict}, fn key, {inc, exc} = acc -> case fetch(exc, key) do {:ok, value} -> {put(inc, key, value), delete(exc, key)} :error -> acc end end) end defoverridable merge: 2, merge: 3, equal?: 2, to_list: 1, keys: 1, values: 1, take: 2, drop: 2, get: 2, get: 3, fetch!: 2, has_key?: 2, put_new: 3, pop: 2, pop: 3, split: 2, update: 4, update!: 3, get_and_update: 3, get_lazy: 3, pop_lazy: 3, put_new_lazy: 3 end end defmacrop target(dict) do quote do case unquote(dict) do %{__struct__: x} when is_atom(x) -> x %{} -> Map x when is_list(x) -> Keyword x -> unsupported_dict(x) end end end @doc """ Returns a list of all keys in `dict`. The keys are not guaranteed to be in any order. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> Enum.sort(Dict.keys(dict)) [:a, :b] """ @spec keys(t) :: [key] def keys(dict) do target(dict).keys(dict) end @doc """ Returns a list of all values in `dict`. The values are not guaranteed to be in any order. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> Enum.sort(Dict.values(dict)) [1, 2] """ @spec values(t) :: [value] def values(dict) do target(dict).values(dict) end @doc """ Returns the number of elements in `dict`. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> Dict.size(dict) 2 """ @spec size(t) :: non_neg_integer def size(dict) do target(dict).size(dict) end @doc """ Returns whether the given `key` exists in the given `dict`. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> Dict.has_key?(dict, :a) true iex> Dict.has_key?(dict, :b) false """ @spec has_key?(t, key) :: boolean def has_key?(dict, key) do target(dict).has_key?(dict, key) end @doc """ Returns the value associated with `key` in `dict`. If `dict` does not contain `key`, returns `default` (or `nil` if not provided). ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> Dict.get(dict, :a) 1 iex> Dict.get(dict, :b) nil iex> Dict.get(dict, :b, 3) 3 """ @spec get(t, key, value) :: value def get(dict, key, default \\ nil) do target(dict).get(dict, key, default) end @doc """ Returns the value associated with `key` in `dict`. If `dict` does not contain `key`, it lazily evaluates `fun` and returns its result. This is useful if the default value is very expensive to calculate or generally difficult to set-up and tear-down again. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> fun = fn -> ...> # some expensive operation here ...> :result ...> end iex> Dict.get_lazy(dict, :a, fun) 1 iex> Dict.get_lazy(dict, :b, fun) :result """ @spec get_lazy(t, key, (() -> value)) :: value def get_lazy(dict, key, fun) do target(dict).get_lazy(dict, key, fun) end @doc """ Gets a value from `dict` and updates the value at `key` in one pass. This `fun` argument receives the value of `key` in `dict` (or `nil` if `key` is not present) and must return a two-elements tuple: the "get" value (the value retrieved from the dict which can be operated on before being returned) and the new value to be stored under `key` in `dict`. The returned value is a tuple with the "get" value returned by `fun` and a new dict with the updated value under `key`. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> {get, new_dict} = Dict.get_and_update dict, :a, fn(current_value) -> ...> {current_value + 1, "foo"} ...> end iex> get 2 iex> Dict.get(new_dict, :a) "foo" """ @spec get_and_update(t, key, (value -> {value, value})) :: {value, t} def get_and_update(dict, key, fun) do target(dict).get_and_update(dict, key, fun) end @doc """ Returns `{:ok, value}` associated with `key` in `dict`. If `dict` does not contain `key`, returns `:error`. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> Dict.fetch(dict, :a) {:ok, 1} iex> Dict.fetch(dict, :b) :error """ @spec fetch(t, key) :: value def fetch(dict, key) do target(dict).fetch(dict, key) end @doc """ Returns the value associated with `key` in `dict`. If `dict` does not contain `key`, it raises `KeyError`. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> Dict.fetch!(dict, :a) 1 """ @spec fetch!(t, key) :: value | no_return def fetch!(dict, key) do target(dict).fetch!(dict, key) end @doc """ Stores the given `value` under `key` in `dict`. If `dict` already has `key`, the stored value is replaced by the new one. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.put(dict, :a, 3) iex> Dict.get(dict, :a) 3 """ @spec put(t, key, value) :: t def put(dict, key, val) do target(dict).put(dict, key, val) end @doc """ Puts the given `value` under `key` in `dict` unless `key` is already present. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.put_new(dict, :a, 3) iex> Dict.get(dict, :a) 1 """ @spec put_new(t, key, value) :: t def put_new(dict, key, val) do target(dict).put_new(dict, key, val) end @doc """ Evaluates `fun` and puts the result under `key` in `dict` unless `key` is already present. This is useful if the value is very expensive to calculate or generally difficult to set-up and tear-down again. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> fun = fn -> ...> # some expensive operation here ...> 3 ...> end iex> dict = Dict.put_new_lazy(dict, :a, fun) iex> Dict.get(dict, :a) 1 iex> dict = Dict.put_new_lazy(dict, :c, fun) iex> Dict.get(dict, :c) 3 """ @spec put_new_lazy(t, key, (() -> value)) :: t def put_new_lazy(dict, key, fun) do target(dict).put_new_lazy(dict, key, fun) end @doc """ Removes the entry stored under the given `key` from `dict`. If `dict` does not contain `key`, returns the dictionary unchanged. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.delete(dict, :a) iex> Dict.get(dict, :a) nil iex> dict = Enum.into([b: 2], dict_impl.new) iex> Dict.delete(dict, :a) == dict true """ @spec delete(t, key) :: t def delete(dict, key) do target(dict).delete(dict, key) end @doc """ Merges the dict `dict2` into dict `dict1`. If one of the `dict2` entries is found in `dict1`, the conflicting entries in `dict2` have higher precedence. Notice this function is polymorphic as it merges dicts of any type. Each dict implementation also provides a `merge` function, but they can only merge dicts of the same type. ## Examples iex> dict1 = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict2 = Enum.into([a: 3, d: 4], dict_impl.new) iex> dict = Dict.merge(dict1, dict2) iex> [a: Dict.get(dict, :a), b: Dict.get(dict, :b), d: Dict.get(dict, :d)] [a: 3, b: 2, d: 4] """ @spec merge(t, t) :: t def merge(dict1, dict2) do target1 = target(dict1) target2 = target(dict2) if target1 == target2 do target1.merge(dict1, dict2) else do_merge(target1, dict1, dict2, fn(_k, _v1, v2) -> v2 end) end end @doc """ Merges the dict `dict2` into dict `dict1`. If one of the `dict2` entries is found in `dict1`, the function will be invoked to resolve the conflict. Notice this function is polymorphic as it merges dicts of any type. Each dict implementation also provides a `merge` function, but they can only merge dicts of the same type. ## Examples iex> dict1 = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict2 = Enum.into([a: 3, d: 4], dict_impl.new) iex> dict = Dict.merge(dict1, dict2, fn(_k, v1, v2) -> ...> v1 + v2 ...> end) iex> [a: Dict.get(dict, :a), b: Dict.get(dict, :b), d: Dict.get(dict, :d)] [a: 4, b: 2, d: 4] """ @spec merge(t, t, (key, value, value -> value)) :: t def merge(dict1, dict2, fun) do target1 = target(dict1) target2 = target(dict2) if target1 == target2 do target1.merge(dict1, dict2, fun) else do_merge(target1, dict1, dict2, fun) end end defp do_merge(target1, dict1, dict2, fun) do Enumerable.reduce(dict2, {:cont, dict1}, fn({k, v}, acc) -> {:cont, target1.update(acc, k, v, fn(other) -> fun.(k, other, v) end)} end) |> elem(1) end @doc """ Returns the value associated with `key` in `dict` as well as the `dict` without `key`. If `key` is not present in `dict`, then the `dict` will be returned unmodified. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> {v, dict} = Dict.pop dict, :a iex> {v, Enum.sort(dict)} {1, []} iex> dict = Enum.into([a: 1], dict_impl.new) iex> {v, dict} = Dict.pop dict, :b iex> {v, Enum.sort(dict)} {nil, [a: 1]} iex> dict = Enum.into([a: 1], dict_impl.new) iex> {v, dict} = Dict.pop dict, :b, 3 iex> {v, Enum.sort(dict)} {3, [a: 1]} """ @spec pop(t, key, value) :: {value, t} def pop(dict, key, default \\ nil) do target(dict).pop(dict, key, default) end @doc """ Returns the value associated with `key` in `dict` as well as the `dict` without `key`. If `key` is not present in `dict`, then the `dict` will be returned unmodified, and it will lazily evaluate `fun` and return its result instead of the missing value. This is useful if the default value is very expensive to calculate or generally difficult to set-up and tear-down again. ## Examples iex> dict = Enum.into([a: 1], dict_impl.new) iex> fun = fn -> ...> # some expensive operation here ...> :result ...> end iex> {v, dict} = Dict.pop_lazy dict, :a, fun iex> {v, Enum.sort(dict)} {1, []} iex> dict = Enum.into([a: 1], dict_impl.new) iex> fun = fn -> ...> # some expensive operation here ...> :result ...> end iex> {v, dict} = Dict.pop_lazy dict, :b, fun iex> {v, Enum.sort(dict)} {:result, [a: 1]} """ @spec pop_lazy(t, key, (() -> value)) :: {value, t} def pop_lazy(dict, key, fun) do target(dict).pop_lazy(dict, key, fun) end @doc """ Updates a value in `dict` by calling `fun` on the value to get a new value. An exception is generated if `key` is not present in the dict. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.update!(dict, :a, fn(val) -> -val end) iex> Dict.get(dict, :a) -1 """ @spec update!(t, key, (value -> value)) :: t def update!(dict, key, fun) do target(dict).update!(dict, key, fun) end @doc """ Updates a value in `dict` by calling `fun` on the value to get a new value. If `key` is not present in `dict` then `initial` will be stored as the first value. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.update(dict, :c, 3, fn(val) -> -val end) iex> Dict.get(dict, :c) 3 """ @spec update(t, key, value, (value -> value)) :: t def update(dict, key, initial, fun) do target(dict).update(dict, key, initial, fun) end @doc """ Returns a tuple of two dicts, where the first dict contains only entries from `dict` with keys in `keys`, and the second dict contains only entries from `dict` with keys not in `keys`. All non-member keys are ignored. ## Examples iex> dict = Enum.into([a: 1, b: 2, c: 3, d: 4], dict_impl.new) iex> {dict1, dict2} = Dict.split(dict, [:a, :c, :e]) iex> {Dict.to_list(dict1) |> Enum.sort, Dict.to_list(dict2) |> Enum.sort} {[a: 1, c: 3], [b: 2, d: 4]} iex> dict = Enum.into([], dict_impl.new) iex> {dict1, dict2} = Dict.split(dict, [:a, :c]) iex> {Dict.to_list(dict1), Dict.to_list(dict2)} {[], []} iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> {dict1, dict2} = Dict.split(dict, [:a, :b, :c]) iex> {Dict.to_list(dict1) |> Enum.sort, Dict.to_list(dict2)} {[a: 1, b: 2], []} """ @spec split(t, [key]) :: {t, t} def split(dict, keys) do target(dict).split(dict, keys) end @doc """ Returns a new dict where the given `keys` are removed from `dict`. All non-member keys are ignored. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.drop(dict, [:a, :c, :d]) iex> Dict.to_list(dict) [b: 2] iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.drop(dict, [:c, :d]) iex> Dict.to_list(dict) |> Enum.sort [a: 1, b: 2] """ @spec drop(t, [key]) :: t def drop(dict, keys) do target(dict).drop(dict, keys) end @doc """ Returns a new dict where only the keys in `keys` from `dict` are included. All non-member keys are ignored. ## Examples iex> dict = Enum.into([a: 1, b: 2], dict_impl.new) iex> dict = Dict.take(dict, [:a, :c, :d]) iex> Dict.to_list(dict) [a: 1] iex> dict = Dict.take(dict, [:c, :d]) iex> Dict.to_list(dict) [] """ @spec take(t, [key]) :: t def take(dict, keys) do target(dict).take(dict, keys) end @doc false @spec empty(t) :: t def empty(dict) do target(dict).empty(dict) end @doc """ Checks if two dicts are equal using `===`. Notice this function is polymorphic as it compares dicts of any type. Each dict implementation also provides an `equal?` function, but they can only compare dicts of the same type. ## Examples iex> dict1 = Enum.into([a: 2, b: 3, f: 5, c: 123], dict_impl.new) iex> dict2 = [a: 2, b: 3, f: 5, c: 123] iex> Dict.equal?(dict1, dict2) true iex> dict1 = Enum.into([a: 2, b: 3, f: 5, c: 123], dict_impl.new) iex> dict2 = [] iex> Dict.equal?(dict1, dict2) false """ @spec equal?(t, t) :: boolean def equal?(dict1, dict2) do target1 = target(dict1) target2 = target(dict2) cond do target1 == target2 -> target1.equal?(dict1, dict2) target1.size(dict1) == target2.size(dict2) -> Enumerable.reduce(dict2, {:cont, true}, fn({k, v}, _acc) -> case target1.fetch(dict1, k) do {:ok, ^v} -> {:cont, true} _ -> {:halt, false} end end) |> elem(1) true -> false end end @doc """ Returns a list of key-value pairs stored in `dict`. No particular order is enforced. """ @spec to_list(t) :: list def to_list(dict) do target(dict).to_list(dict) end defp unsupported_dict(dict) do raise ArgumentError, "unsupported dict: #{inspect dict}" end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/enum.ex000066400000000000000000002022501254730255300212300ustar00rootroot00000000000000defprotocol Enumerable do @moduledoc """ Enumerable protocol used by `Enum` and `Stream` modules. When you invoke a function in the `Enum` module, the first argument is usually a collection that must implement this protocol. For example, the expression Enum.map([1, 2, 3], &(&1 * 2)) invokes underneath `Enumerable.reduce/3` to perform the reducing operation that builds a mapped list by calling the mapping function `&(&1 * 2)` on every element in the collection and cons'ing the element with an accumulated list. Internally, `Enum.map/2` is implemented as follows: def map(enum, fun) do reducer = fn x, acc -> {:cont, [fun.(x)|acc]} end Enumerable.reduce(enum, {:cont, []}, reducer) |> elem(1) |> :lists.reverse() end Notice the user given function is wrapped into a `reducer` function. The `reducer` function must return a tagged tuple after each step, as described in the `acc/0` type. The reason the accumulator requires a tagged tuple is to allow the reducer function to communicate to the underlying enumerable the end of enumeration, allowing any open resource to be properly closed. It also allows suspension of the enumeration, which is useful when interleaving between many enumerables is required (as in zip). Finally, `Enumerable.reduce/3` will return another tagged tuple, as represented by the `result/0` type. """ @typedoc """ The accumulator value for each step. It must be a tagged tuple with one of the following "tags": * `:cont` - the enumeration should continue * `:halt` - the enumeration should halt immediately * `:suspend` - the enumeration should be suspended immediately Depending on the accumulator value, the result returned by `Enumerable.reduce/3` will change. Please check the `result` type docs for more information. In case a reducer function returns a `:suspend` accumulator, it must be explicitly handled by the caller and never leak. """ @type acc :: {:cont, term} | {:halt, term} | {:suspend, term} @typedoc """ The reducer function. Should be called with the collection element and the accumulator contents. Returns the accumulator for the next enumeration step. """ @type reducer :: (term, term -> acc) @typedoc """ The result of the reduce operation. It may be *done* when the enumeration is finished by reaching its end, or *halted*/*suspended* when the enumeration was halted or suspended by the reducer function. In case a reducer function returns the `:suspend` accumulator, the `:suspended` tuple must be explicitly handled by the caller and never leak. In practice, this means regular enumeration functions just need to be concerned about `:done` and `:halted` results. Furthermore, a `:suspend` call must always be followed by another call, eventually halting or continuing until the end. """ @type result :: {:done, term} | {:halted, term} | {:suspended, term, continuation} @typedoc """ A partially applied reduce function. The continuation is the closure returned as a result when the enumeration is suspended. When invoked, it expects a new accumulator and it returns the result. A continuation is easily implemented as long as the reduce function is defined in a tail recursive fashion. If the function is tail recursive, all the state is passed as arguments, so the continuation would simply be the reducing function partially applied. """ @type continuation :: (acc -> result) @doc """ Reduces the collection into a value. Most of the operations in `Enum` are implemented in terms of reduce. This function should apply the given `reducer` function to each item in the collection and proceed as expected by the returned accumulator. As an example, here is the implementation of `reduce` for lists: def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)} def reduce([], {:cont, acc}, _fun), do: {:done, acc} def reduce([h|t], {:cont, acc}, fun), do: reduce(t, fun.(h, acc), fun) """ @spec reduce(t, acc, reducer) :: result def reduce(collection, acc, fun) @doc """ Checks if a value exists within the collection. It should return `{:ok, boolean}`. If `{:error, __MODULE__}` is returned a default algorithm using `reduce` and the match (`===`) operator is used. This algorithm runs in linear time. Please force use of the default algorithm unless you can implement an algorithm that is significantly faster. """ @spec member?(t, term) :: {:ok, boolean} | {:error, module} def member?(collection, value) @doc """ Retrieves the collection's size. It should return `{:ok, size}`. If `{:error, __MODULE__}` is returned a default algorithm using `reduce` and the match (`===`) operator is used. This algorithm runs in linear time. Please force use of the default algorithm unless you can implement an algorithm that is significantly faster. """ @spec count(t) :: {:ok, non_neg_integer} | {:error, module} def count(collection) end defmodule Enum do import Kernel, except: [max: 2, min: 2] @moduledoc """ Provides a set of algorithms that enumerate over collections according to the `Enumerable` protocol: iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end) [2, 4, 6] Some particular types, like dictionaries, yield a specific format on enumeration. For dicts, the argument is always a `{key, value}` tuple: iex> dict = %{a: 1, b: 2} iex> Enum.map(dict, fn {k, v} -> {k, v * 2} end) [a: 2, b: 4] Note that the functions in the `Enum` module are eager: they always start the enumeration of the given collection. The `Stream` module allows lazy enumeration of collections and provides infinite streams. Since the majority of the functions in `Enum` enumerate the whole collection and return a list as result, infinite streams need to be carefully used with such functions, as they can potentially run forever. For example: Enum.each Stream.cycle([1, 2, 3]), &IO.puts(&1) """ @compile :inline_list_funcs @type t :: Enumerable.t @type element :: any @type index :: non_neg_integer @type default :: any # Require Stream.Reducers and its callbacks require Stream.Reducers, as: R defmacrop skip(acc) do acc end defmacrop next(_, entry, acc) do quote do: [unquote(entry)|unquote(acc)] end defmacrop acc(h, n, _) do quote do: {unquote(h), unquote(n)} end defmacrop next_with_acc(f, entry, h, n, _) do quote do {[unquote(entry)|unquote(h)], unquote(n)} end end @doc """ Invokes the given `fun` for each item in the `collection` and returns `false` if at least one invocation returns `false` or `nil`. Otherwise returns `true`. ## Examples iex> Enum.all?([2, 4, 6], fn(x) -> rem(x, 2) == 0 end) true iex> Enum.all?([2, 3, 4], fn(x) -> rem(x, 2) == 0 end) false If no function is given, it defaults to checking if all items in the collection are truthy values. iex> Enum.all?([1, 2, 3]) true iex> Enum.all?([1, nil, 3]) false """ @spec all?(t) :: boolean @spec all?(t, (element -> as_boolean(term))) :: boolean def all?(collection, fun \\ fn(x) -> x end) def all?(collection, fun) when is_list(collection) do do_all?(collection, fun) end def all?(collection, fun) do Enumerable.reduce(collection, {:cont, true}, fn(entry, _) -> if fun.(entry), do: {:cont, true}, else: {:halt, false} end) |> elem(1) end @doc """ Invokes the given `fun` for each item in the `collection` and returns `true` if at least one invocation returns a truthy value. Returns `false` otherwise. ## Examples iex> Enum.any?([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) false iex> Enum.any?([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) true If no function is given, it defaults to checking if at least one item in the collection is a truthy value. iex> Enum.any?([false, false, false]) false iex> Enum.any?([false, true, false]) true """ @spec any?(t) :: boolean @spec any?(t, (element -> as_boolean(term))) :: boolean def any?(collection, fun \\ fn(x) -> x end) def any?(collection, fun) when is_list(collection) do do_any?(collection, fun) end def any?(collection, fun) do Enumerable.reduce(collection, {:cont, false}, fn(entry, _) -> if fun.(entry), do: {:halt, true}, else: {:cont, false} end) |> elem(1) end @doc """ Finds the element at the given index (zero-based). Returns `default` if index is out of bounds. Note this operation takes linear time. In order to access the element at index `n`, it will need to traverse `n` previous elements. ## Examples iex> Enum.at([2, 4, 6], 0) 2 iex> Enum.at([2, 4, 6], 2) 6 iex> Enum.at([2, 4, 6], 4) nil iex> Enum.at([2, 4, 6], 4, :none) :none """ @spec at(t, integer, default) :: element | default def at(collection, n, default \\ nil) do case fetch(collection, n) do {:ok, h} -> h :error -> default end end @doc """ Shortcut to `chunk(collection, n, n)`. """ @spec chunk(t, non_neg_integer) :: [list] def chunk(collection, n), do: chunk(collection, n, n, nil) @doc """ Returns a collection of lists containing `n` items each, where each new chunk starts `step` elements into the collection. `step` is optional and, if not passed, defaults to `n`, i.e. chunks do not overlap. If the final chunk does not have `n` elements to fill the chunk, elements are taken as necessary from `pad` if it was passed. If `pad` is passed and does not have enough elements to fill the chunk, then the chunk is returned anyway with less than `n` elements. If `pad` is not passed at all or is `nil`, then the partial chunk is discarded from the result. ## Examples iex> Enum.chunk([1, 2, 3, 4, 5, 6], 2) [[1, 2], [3, 4], [5, 6]] iex> Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2) [[1, 2, 3], [3, 4, 5]] iex> Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2, [7]) [[1, 2, 3], [3, 4, 5], [5, 6, 7]] iex> Enum.chunk([1, 2, 3, 4, 5, 6], 3, 3, []) [[1, 2, 3], [4, 5, 6]] """ @spec chunk(t, non_neg_integer, non_neg_integer, t | nil) :: [list] def chunk(collection, n, step, pad \\ nil) when n > 0 and step > 0 do limit = :erlang.max(n, step) {acc, {buffer, i}} = reduce(collection, {[], {[], 0}}, R.chunk(n, step, limit)) if is_nil(pad) || i == 0 do :lists.reverse(acc) else buffer = :lists.reverse(buffer, take(pad, n - i)) :lists.reverse([buffer|acc]) end end @doc """ Splits `collection` on every element for which `fun` returns a new value. ## Examples iex> Enum.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1)) [[1], [2, 2], [3], [4, 4, 6], [7, 7]] """ @spec chunk_by(t, (element -> any)) :: [list] def chunk_by(collection, fun) do {acc, res} = reduce(collection, {[], nil}, R.chunk_by(fun)) case res do {buffer, _} -> :lists.reverse([:lists.reverse(buffer) | acc]) nil -> [] end end @doc """ Given an enumerable of enumerables, concatenates the enumerables into a single list. ## Examples iex> Enum.concat([1..3, 4..6, 7..9]) [1, 2, 3, 4, 5, 6, 7, 8, 9] iex> Enum.concat([[1, [2], 3], [4], [5, 6]]) [1, [2], 3, 4, 5, 6] """ @spec concat(t) :: t def concat(enumerables) do do_concat(enumerables) end @doc """ Concatenates the enumerable on the right with the enumerable on the left. This function produces the same result as the `Kernel.++/2` operator for lists. ## Examples iex> Enum.concat(1..3, 4..6) [1, 2, 3, 4, 5, 6] iex> Enum.concat([1, 2, 3], [4, 5, 6]) [1, 2, 3, 4, 5, 6] """ @spec concat(t, t) :: t def concat(left, right) when is_list(left) and is_list(right) do left ++ right end def concat(left, right) do do_concat([left, right]) end defp do_concat(enumerable) do fun = &[&1|&2] reduce(enumerable, [], &reduce(&1, &2, fun)) |> :lists.reverse end @doc """ Returns the collection's size. ## Examples iex> Enum.count([1, 2, 3]) 3 """ @spec count(t) :: non_neg_integer def count(collection) when is_list(collection) do :erlang.length(collection) end def count(collection) do case Enumerable.count(collection) do {:ok, value} when is_integer(value) -> value {:error, module} -> module.reduce(collection, {:cont, 0}, fn _, acc -> {:cont, acc + 1} end) |> elem(1) end end @doc """ Returns the count of items in the collection for which `fun` returns a truthy value. ## Examples iex> Enum.count([1, 2, 3, 4, 5], fn(x) -> rem(x, 2) == 0 end) 2 """ @spec count(t, (element -> as_boolean(term))) :: non_neg_integer def count(collection, fun) do Enumerable.reduce(collection, {:cont, 0}, fn(entry, acc) -> {:cont, if(fun.(entry), do: acc + 1, else: acc)} end) |> elem(1) end @doc """ Enumerates the collection, returning a list where all consecutive duplicated elements are collapsed to a single element. Elements are compared using `===`. ## Examples iex> Enum.dedup([1, 2, 3, 3, 2, 1]) [1, 2, 3, 2, 1] """ @spec dedup(t) :: list def dedup(collection) do dedup_by(collection, fn x -> x end) end @doc """ Enumerates the collection, returning a list where all consecutive duplicated elements are collapsed to a single element. The function `fun` maps every element to a term which is used to determine if two elements are duplicates. ## Examples iex> Enum.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) [{1, :x}, {2, :y}, {1, :x}] iex> Enum.dedup_by([5, 1, 2, 3, 2, 1], fn x -> x > 2 end) [5, 1, 3, 2] """ @spec dedup_by(t, (element -> term)) :: list def dedup_by(collection, fun) when is_function(fun, 1) do {list, _} = reduce(collection, {[], []}, R.dedup(fun)) :lists.reverse(list) end @doc """ Drops the first `count` items from `collection`. If a negative value `count` is given, the last `count` values will be dropped. The collection is enumerated once to retrieve the proper index and the remaining calculation is performed from the end. ## Examples iex> Enum.drop([1, 2, 3], 2) [3] iex> Enum.drop([1, 2, 3], 10) [] iex> Enum.drop([1, 2, 3], 0) [1, 2, 3] iex> Enum.drop([1, 2, 3], -1) [1, 2] """ @spec drop(t, integer) :: list def drop(collection, count) when is_list(collection) and count >= 0 do do_drop(collection, count) end def drop(collection, count) when count >= 0 do res = reduce(collection, count, fn x, acc when is_list(acc) -> [x|acc] x, 0 -> [x] _, acc when acc > 0 -> acc - 1 end) if is_list(res), do: :lists.reverse(res), else: [] end def drop(collection, count) when count < 0 do do_drop(reverse(collection), abs(count)) |> :lists.reverse end @doc """ Drops items at the beginning of `collection` while `fun` returns a truthy value. ## Examples iex> Enum.drop_while([1, 2, 3, 4, 5], fn(x) -> x < 3 end) [3, 4, 5] """ @spec drop_while(t, (element -> as_boolean(term))) :: list def drop_while(collection, fun) when is_list(collection) do do_drop_while(collection, fun) end def drop_while(collection, fun) do {res, _} = reduce(collection, {[], true}, R.drop_while(fun)) :lists.reverse(res) end @doc """ Invokes the given `fun` for each item in the `collection`. Returns `:ok`. ## Examples Enum.each(["some", "example"], fn(x) -> IO.puts x end) "some" "example" #=> :ok """ @spec each(t, (element -> any)) :: :ok def each(collection, fun) when is_list(collection) do :lists.foreach(fun, collection) :ok end def each(collection, fun) do reduce(collection, nil, fn(entry, _) -> fun.(entry) nil end) :ok end @doc """ Returns `true` if the collection is empty, otherwise `false`. ## Examples iex> Enum.empty?([]) true iex> Enum.empty?([1, 2, 3]) false """ @spec empty?(t) :: boolean def empty?(collection) when is_list(collection) do collection == [] end def empty?(collection) do Enumerable.reduce(collection, {:cont, true}, fn(_, _) -> {:halt, false} end) |> elem(1) end @doc """ Finds the element at the given index (zero-based). Returns `{:ok, element}` if found, otherwise `:error`. A negative index can be passed, which means the collection is enumerated once and the index is counted from the end (i.e. `-1` fetches the last element). Note this operation takes linear time. In order to access the element at index `n`, it will need to traverse `n` previous elements. ## Examples iex> Enum.fetch([2, 4, 6], 0) {:ok, 2} iex> Enum.fetch([2, 4, 6], 2) {:ok, 6} iex> Enum.fetch([2, 4, 6], 4) :error """ @spec fetch(t, integer) :: {:ok, element} | :error def fetch(collection, n) when is_list(collection) and is_integer(n) and n >= 0 do do_fetch(collection, n) end def fetch(collection, n) when is_integer(n) and n >= 0 do res = Enumerable.reduce(collection, {:cont, 0}, fn(entry, acc) -> if acc == n do {:halt, entry} else {:cont, acc + 1} end end) case res do {:halted, entry} -> {:ok, entry} {:done, _} -> :error end end def fetch(collection, n) when is_integer(n) and n < 0 do do_fetch(reverse(collection), abs(n + 1)) end @doc """ Finds the element at the given index (zero-based). Raises `OutOfBoundsError` if the given position is outside the range of the collection. Note this operation takes linear time. In order to access the element at index `n`, it will need to traverse `n` previous elements. ## Examples iex> Enum.fetch!([2, 4, 6], 0) 2 iex> Enum.fetch!([2, 4, 6], 2) 6 iex> Enum.fetch!([2, 4, 6], 4) ** (Enum.OutOfBoundsError) out of bounds error """ @spec fetch!(t, integer) :: element | no_return def fetch!(collection, n) do case fetch(collection, n) do {:ok, h} -> h :error -> raise Enum.OutOfBoundsError end end @doc """ Filters the collection, i.e. returns only those elements for which `fun` returns a truthy value. ## Examples iex> Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) [2] """ @spec filter(t, (element -> as_boolean(term))) :: list def filter(collection, fun) when is_list(collection) do for item <- collection, fun.(item), do: item end def filter(collection, fun) do reduce(collection, [], R.filter(fun)) |> :lists.reverse end @doc """ Filters the collection and maps its values in one pass. ## Examples iex> Enum.filter_map([1, 2, 3], fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) [4] """ @spec filter_map(t, (element -> as_boolean(term)), (element -> element)) :: list def filter_map(collection, filter, mapper) when is_list(collection) do for item <- collection, filter.(item), do: mapper.(item) end def filter_map(collection, filter, mapper) do reduce(collection, [], R.filter_map(filter, mapper)) |> :lists.reverse end @doc """ Returns the first item for which `fun` returns a truthy value. If no such item is found, returns `ifnone`. ## Examples iex> Enum.find([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) nil iex> Enum.find([2, 4, 6], 0, fn(x) -> rem(x, 2) == 1 end) 0 iex> Enum.find([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) 3 """ @spec find(t, default, (element -> any)) :: element | default def find(collection, ifnone \\ nil, fun) def find(collection, ifnone, fun) when is_list(collection) do do_find(collection, ifnone, fun) end def find(collection, ifnone, fun) do Enumerable.reduce(collection, {:cont, ifnone}, fn(entry, ifnone) -> if fun.(entry), do: {:halt, entry}, else: {:cont, ifnone} end) |> elem(1) end @doc """ Similar to `find/3`, but returns the value of the function invocation instead of the element itself. ## Examples iex> Enum.find_value([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) nil iex> Enum.find_value([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) true iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1) "no bools!" """ @spec find_value(t, any, (element -> any)) :: any | :nil def find_value(collection, ifnone \\ nil, fun) def find_value(collection, ifnone, fun) when is_list(collection) do do_find_value(collection, ifnone, fun) end def find_value(collection, ifnone, fun) do Enumerable.reduce(collection, {:cont, ifnone}, fn(entry, ifnone) -> fun_entry = fun.(entry) if fun_entry, do: {:halt, fun_entry}, else: {:cont, ifnone} end) |> elem(1) end @doc """ Similar to `find/3`, but returns the index (zero-based) of the element instead of the element itself. ## Examples iex> Enum.find_index([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) nil iex> Enum.find_index([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) 1 """ @spec find_index(t, (element -> any)) :: index | :nil def find_index(collection, fun) when is_list(collection) do do_find_index(collection, 0, fun) end def find_index(collection, fun) do res = Enumerable.reduce(collection, {:cont, 0}, fn(entry, acc) -> if fun.(entry), do: {:halt, acc}, else: {:cont, acc + 1} end) case res do {:halted, entry} -> entry {:done, _} -> nil end end @doc """ Returns a new collection appending the result of invoking `fun` on each corresponding item of `collection`. The given function should return an enumerable. ## Examples iex> Enum.flat_map([:a, :b, :c], fn(x) -> [x, x] end) [:a, :a, :b, :b, :c, :c] iex> Enum.flat_map([{1, 3}, {4, 6}], fn({x, y}) -> x..y end) [1, 2, 3, 4, 5, 6] """ @spec flat_map(t, (element -> t)) :: list def flat_map(collection, fun) do reduce(collection, [], fn(entry, acc) -> reduce(fun.(entry), acc, &[&1|&2]) end) |> :lists.reverse end @doc """ Maps and reduces a collection, flattening the given results. It expects an accumulator and a function that receives each stream item and an accumulator, and must return a tuple containing a new stream (often a list) with the new accumulator or a tuple with `:halt` as first element and the accumulator as second. ## Examples iex> enum = 1..100 iex> n = 3 iex> Enum.flat_map_reduce(enum, 0, fn i, acc -> ...> if acc < n, do: {[i], acc + 1}, else: {:halt, acc} ...> end) {[1, 2, 3], 3} """ @spec flat_map_reduce(t, acc, fun) :: {[any], any} when fun: (element, acc -> {t, acc} | {:halt, acc}), acc: any def flat_map_reduce(collection, acc, fun) do {_, {list, acc}} = Enumerable.reduce(collection, {:cont, {[], acc}}, fn(entry, {list, acc}) -> case fun.(entry, acc) do {:halt, acc} -> {:halt, {list, acc}} {[], acc} -> {:cont, {list, acc}} {[entry], acc} -> {:cont, {[entry|list], acc}} {entries, acc} -> {:cont, {reduce(entries, list, &[&1|&2]), acc}} end end) {:lists.reverse(list), acc} end @doc """ Intersperses `element` between each element of the enumeration. Complexity: O(n) ## Examples iex> Enum.intersperse([1, 2, 3], 0) [1, 0, 2, 0, 3] iex> Enum.intersperse([1], 0) [1] iex> Enum.intersperse([], 0) [] """ @spec intersperse(t, element) :: list def intersperse(collection, element) do list = reduce(collection, [], fn(x, acc) -> [x, element | acc] end) |> :lists.reverse() case list do [] -> [] [_|t] -> t # Head is a superfluous intersperser element end end @doc """ Inserts the given enumerable into a collectable. ## Examples iex> Enum.into([1, 2], [0]) [0, 1, 2] iex> Enum.into([a: 1, b: 2], %{}) %{a: 1, b: 2} """ @spec into(Enumerable.t, Collectable.t) :: Collectable.t def into(collection, list) when is_list(list) do list ++ to_list(collection) end def into(%{__struct__: _} = collection, collectable) do do_into(collection, collectable) end def into(collection, %{__struct__: _} = collectable) do do_into(collection, collectable) end def into(%{} = collection, %{} = collectable) do Map.merge(collectable, collection) end def into(collection, %{} = collectable) when is_list(collection) do Map.merge(collectable, :maps.from_list(collection)) end def into(collection, %{} = collectable) do reduce(collection, collectable, fn {k, v}, acc -> Map.put(acc, k, v) end) end def into(collection, collectable) do do_into(collection, collectable) end defp do_into(collection, collectable) do {initial, fun} = Collectable.into(collectable) into(collection, initial, fun, fn x, acc -> fun.(acc, {:cont, x}) end) end @doc """ Inserts the given enumerable into a collectable according to the transformation function. ## Examples iex> Enum.into([2, 3], [3], fn x -> x * 3 end) [3, 6, 9] """ @spec into(Enumerable.t, Collectable.t, (term -> term)) :: Collectable.t def into(collection, list, transform) when is_list(list) and is_function(transform, 1) do list ++ map(collection, transform) end def into(collection, collectable, transform) when is_function(transform, 1) do {initial, fun} = Collectable.into(collectable) into(collection, initial, fun, fn x, acc -> fun.(acc, {:cont, transform.(x)}) end) end defp into(collection, initial, fun, callback) do try do reduce(collection, initial, callback) catch kind, reason -> stacktrace = System.stacktrace fun.(initial, :halt) :erlang.raise(kind, reason, stacktrace) else acc -> fun.(acc, :done) end end @doc """ Joins the given `collection` into a binary using `joiner` as a separator. If `joiner` is not passed at all, it defaults to the empty binary. All items in the collection must be convertible to a binary, otherwise an error is raised. ## Examples iex> Enum.join([1, 2, 3]) "123" iex> Enum.join([1, 2, 3], " = ") "1 = 2 = 3" """ @spec join(t, String.t) :: String.t def join(collection, joiner \\ "") def join(collection, joiner) when is_binary(joiner) do reduced = reduce(collection, :first, fn entry, :first -> enum_to_string(entry) entry, acc -> [acc, joiner|enum_to_string(entry)] end) if reduced == :first do "" else IO.iodata_to_binary reduced end end @doc """ Returns a new collection, where each item is the result of invoking `fun` on each corresponding item of `collection`. For dicts, the function expects a key-value tuple. ## Examples iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end) [2, 4, 6] iex> Enum.map([a: 1, b: 2], fn({k, v}) -> {k, -v} end) [a: -1, b: -2] """ @spec map(t, (element -> any)) :: list def map(collection, fun) when is_list(collection) do for item <- collection, do: fun.(item) end def map(collection, fun) do reduce(collection, [], R.map(fun)) |> :lists.reverse end @doc """ Maps and joins the given `collection` in one pass. `joiner` can be either a binary or a list and the result will be of the same type as `joiner`. If `joiner` is not passed at all, it defaults to an empty binary. All items in the collection must be convertible to a binary, otherwise an error is raised. ## Examples iex> Enum.map_join([1, 2, 3], &(&1 * 2)) "246" iex> Enum.map_join([1, 2, 3], " = ", &(&1 * 2)) "2 = 4 = 6" """ @spec map_join(t, String.t, (element -> any)) :: String.t def map_join(collection, joiner \\ "", mapper) def map_join(collection, joiner, mapper) when is_binary(joiner) do reduced = reduce(collection, :first, fn entry, :first -> enum_to_string(mapper.(entry)) entry, acc -> [acc, joiner|enum_to_string(mapper.(entry))] end) if reduced == :first do "" else IO.iodata_to_binary reduced end end @doc """ Invokes the given `fun` for each item in the `collection` while also keeping an accumulator. Returns a tuple where the first element is the mapped collection and the second one is the final accumulator. For dicts, the first tuple element must be a `{key, value}` tuple. ## Examples iex> Enum.map_reduce([1, 2, 3], 0, fn(x, acc) -> {x * 2, x + acc} end) {[2, 4, 6], 6} """ @spec map_reduce(t, any, (element, any -> {any, any})) :: {any, any} def map_reduce(collection, acc, fun) when is_list(collection) do :lists.mapfoldl(fun, acc, collection) end def map_reduce(collection, acc, fun) do {list, acc} = reduce(collection, {[], acc}, fn(entry, {list, acc}) -> {new_entry, acc} = fun.(entry, acc) {[new_entry|list], acc} end) {:lists.reverse(list), acc} end @doc """ Returns the maximum value. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.max([1, 2, 3]) 3 """ @spec max(t) :: element | no_return def max(collection) do reduce(collection, &Kernel.max(&1, &2)) end @doc """ Returns the maximum value as calculated by the given function. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.max_by(["a", "aa", "aaa"], fn(x) -> String.length(x) end) "aaa" """ @spec max_by(t, (element -> any)) :: element | no_return def max_by([h|t], fun) do reduce(t, {h, fun.(h)}, fn(entry, {_, fun_max} = old) -> fun_entry = fun.(entry) if(fun_entry > fun_max, do: {entry, fun_entry}, else: old) end) |> elem(0) end def max_by([], _fun) do raise Enum.EmptyError end def max_by(collection, fun) do result = reduce(collection, :first, fn entry, {_, fun_max} = old -> fun_entry = fun.(entry) if(fun_entry > fun_max, do: {entry, fun_entry}, else: old) entry, :first -> {entry, fun.(entry)} end) case result do :first -> raise Enum.EmptyError {entry, _} -> entry end end @doc """ Checks if `value` exists within the `collection`. Membership is tested with the match (`===`) operator, although enumerables like ranges may include floats inside the given range. ## Examples iex> Enum.member?(1..10, 5) true iex> Enum.member?([:a, :b, :c], :d) false """ @spec member?(t, element) :: boolean def member?(collection, value) when is_list(collection) do :lists.member(value, collection) end def member?(collection, value) do case Enumerable.member?(collection, value) do {:ok, value} when is_boolean(value) -> value {:error, module} -> module.reduce(collection, {:cont, false}, fn v, _ when v === value -> {:halt, true} _, _ -> {:cont, false} end) |> elem(1) end end @doc """ Returns the minimum value. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.min([1, 2, 3]) 1 """ @spec min(t) :: element | no_return def min(collection) do reduce(collection, &Kernel.min(&1, &2)) end @doc """ Returns the minimum value as calculated by the given function. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.min_by(["a", "aa", "aaa"], fn(x) -> String.length(x) end) "a" """ @spec min_by(t, (element -> any)) :: element | no_return def min_by([h|t], fun) do reduce(t, {h, fun.(h)}, fn(entry, {_, fun_min} = old) -> fun_entry = fun.(entry) if(fun_entry < fun_min, do: {entry, fun_entry}, else: old) end) |> elem(0) end def min_by([], _fun) do raise Enum.EmptyError end def min_by(collection, fun) do result = reduce(collection, :first, fn entry, {_, fun_min} = old -> fun_entry = fun.(entry) if(fun_entry < fun_min, do: {entry, fun_entry}, else: old) entry, :first -> {entry, fun.(entry)} end) case result do :first -> raise Enum.EmptyError {entry, _} -> entry end end @doc """ Returns a tuple with the minimum and maximum values. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.minmax([2, 3, 1]) {1, 3} """ @spec minmax(t) :: element | no_return def minmax(collection) do result = Enum.reduce(collection, :first, fn entry, {min_value, max_value} -> {Kernel.min(entry, min_value), Kernel.max(entry, max_value)} entry, :first -> {entry, entry} end) case result do :first -> raise Enum.EmptyError result -> result end end @doc """ Returns a tuple with the minimum and maximum values as calculated by the given function. Raises `EmptyError` if the collection is empty. ## Examples iex> Enum.minmax_by(["aaa", "bb", "c"], fn(x) -> String.length(x) end) {"c", "aaa"} """ @spec minmax_by(t, (element -> any)) :: element | no_return def minmax_by(collection, fun) do result = Enum.reduce(collection, :first, fn entry, {{_, fun_min} = acc_min, {_, fun_max} = acc_max} -> fun_entry = fun.(entry) if fun_entry < fun_min, do: acc_min = {entry, fun_entry} if fun_entry > fun_max, do: acc_max = {entry, fun_entry} {acc_min, acc_max} entry, :first -> fun_entry = fun.(entry) {{entry, fun_entry}, {entry, fun_entry}} end) case result do :first -> raise Enum.EmptyError {{min_entry, _}, {max_entry, _}} -> {min_entry, max_entry} end end @doc """ Returns the sum of all values. Raises `ArithmeticError` if collection contains a non-numeric value. ## Examples iex> Enum.sum([1, 2, 3]) 6 """ @spec sum(t) :: number def sum(collection) do reduce(collection, 0, &+/2) end @doc """ Partitions `collection` into two collections, where the first one contains elements for which `fun` returns a truthy value, and the second one -- for which `fun` returns `false` or `nil`. ## Examples iex> Enum.partition([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) {[2], [1, 3]} """ @spec partition(t, (element -> any)) :: {list, list} def partition(collection, fun) do {acc1, acc2} = reduce(collection, {[], []}, fn(entry, {acc1, acc2}) -> if fun.(entry) do {[entry|acc1], acc2} else {acc1, [entry|acc2]} end end) {:lists.reverse(acc1), :lists.reverse(acc2)} end @doc """ Splits `collection` into groups based on `fun`. The result is a dict (by default a map) where each key is a group and each value is a list of elements from `collection` for which `fun` returned that group. Ordering is not necessarily preserved. ## Examples iex> Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1) %{3 => ["cat", "ant"], 7 => ["buffalo"], 5 => ["dingo"]} """ @spec group_by(t, dict, (element -> any)) :: dict when dict: Dict.t def group_by(collection, dict \\ %{}, fun) do reduce(collection, dict, fn(entry, categories) -> Dict.update(categories, fun.(entry), [entry], &[entry|&1]) end) end @doc """ Invokes `fun` for each element in the collection passing that element and the accumulator `acc` as arguments. `fun`'s return value is stored in `acc`. Returns the accumulator. ## Examples iex> Enum.reduce([1, 2, 3], 0, fn(x, acc) -> x + acc end) 6 """ @spec reduce(t, any, (element, any -> any)) :: any def reduce(collection, acc, fun) when is_list(collection) do :lists.foldl(fun, acc, collection) end def reduce(%{__struct__: _} = collection, acc, fun) do Enumerable.reduce(collection, {:cont, acc}, fn x, acc -> {:cont, fun.(x, acc)} end) |> elem(1) end def reduce(%{} = collection, acc, fun) do :maps.fold(fn k, v, acc -> fun.({k, v}, acc) end, acc, collection) end def reduce(collection, acc, fun) do Enumerable.reduce(collection, {:cont, acc}, fn x, acc -> {:cont, fun.(x, acc)} end) |> elem(1) end @doc """ Invokes `fun` for each element in the collection passing that element and the accumulator `acc` as arguments. `fun`'s return value is stored in `acc`. The first element of the collection is used as the initial value of `acc`. If you wish to use another value for `acc`, use `Enumerable.reduce/3`. This function won't call the specified function for enumerables that are 1-element long. Returns the accumulator. ## Examples iex> Enum.reduce([1, 2, 3, 4], fn(x, acc) -> x * acc end) 24 """ @spec reduce(t, (element, any -> any)) :: any def reduce([h|t], fun) do reduce(t, h, fun) end def reduce([], _fun) do raise Enum.EmptyError end def reduce(collection, fun) do result = Enumerable.reduce(collection, {:cont, :first}, fn x, :first -> {:cont, {:acc, x}} x, {:acc, acc} -> {:cont, {:acc, fun.(x, acc)}} end) |> elem(1) case result do :first -> raise Enum.EmptyError {:acc, acc} -> acc end end @doc """ Reduces the collection until halt is emitted. The return value for `fun` is expected to be `{:cont, acc}`, return `{:halt, acc}` to end the reduction early. Returns the accumulator. ## Examples iex> Enum.reduce_while(1..100, 0, fn i, acc -> ...> if i < 3, do: {:cont, acc + i}, else: {:halt, acc} ...> end) 3 """ def reduce_while(collection, acc, fun) do Enumerable.reduce(collection, {:cont, acc}, fun) |> elem(1) end @doc """ Returns elements of collection for which `fun` returns `false` or `nil`. ## Examples iex> Enum.reject([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) [1, 3] """ @spec reject(t, (element -> as_boolean(term))) :: list def reject(collection, fun) when is_list(collection) do for item <- collection, !fun.(item), do: item end def reject(collection, fun) do reduce(collection, [], R.reject(fun)) |> :lists.reverse end @doc """ Reverses the collection. ## Examples iex> Enum.reverse([1, 2, 3]) [3, 2, 1] """ @spec reverse(t) :: list def reverse(collection) when is_list(collection) do :lists.reverse(collection) end def reverse(collection) do reverse(collection, []) end @doc """ Reverses the collection and appends the tail. This is an optimization for `Enum.concat(Enum.reverse(collection), tail)`. ## Examples iex> Enum.reverse([1, 2, 3], [4, 5, 6]) [3, 2, 1, 4, 5, 6] """ @spec reverse(t, t) :: list def reverse(collection, tail) when is_list(collection) and is_list(tail) do :lists.reverse(collection, tail) end def reverse(collection, tail) do reduce(collection, to_list(tail), fn(entry, acc) -> [entry|acc] end) end @doc """ Reverses the collection in the range from initial position `first` through `count` elements. If `count` is greater than the size of the rest of the collection, then this function will reverse the rest of the collection. ## Examples iex> Enum.reverse_slice([1, 2, 3, 4, 5, 6], 2, 4) [1, 2, 6, 5, 4, 3] """ @spec reverse_slice(t, non_neg_integer, non_neg_integer) :: list def reverse_slice(collection, start, count) when start >= 0 and count >= 0 do list = reverse(collection) length = length(list) count = Kernel.min(count, length - start) if count > 0 do reverse_slice(list, length, start + count, count, []) else :lists.reverse(list) end end @doc """ Returns a random element of a collection. Raises `EmptyError` if the collection is empty. Notice that you need to explicitly call `:random.seed/1` and set a seed value for the random algorithm. Otherwise, the default seed will be set which will always return the same result. For example, one could do the following to set a seed dynamically: :random.seed(:os.timestamp) The implementation is based on the [reservoir sampling](http://en.wikipedia.org/wiki/Reservoir_sampling#Relation_to_Fisher-Yates_shuffle) algorithm. It assumes that the sample being returned can fit into memory; the input collection doesn't have to - it is traversed just once. ## Examples iex> Enum.random([1, 2, 3]) 1 iex> Enum.random([1, 2, 3]) 2 """ @spec random(t) :: element def random(collection) do case random(collection, 1) do [] -> raise Enum.EmptyError [e] -> e end end @doc """ Returns a random sublist of a collection. Notice this function will traverse the whole collection to get the random sublist of collection. If you want the random number between two integers, the best option is to use the :random module. See `random/1` for notes on implementation and random seed. ## Examples iex> Enum.random(1..10, 2) [1, 5] iex> Enum.random(?a..?z, 5) 'tfesm' """ @spec random(t, integer) :: list def random(collection, count) when count > 0 do sample = Tuple.duplicate(nil, count) reducer = fn x, {i, sample} -> j = random_index(i) if i < count do swapped = sample |> elem(j) {i + 1, sample |> put_elem(i, swapped) |> put_elem(j, x)} else if j < count, do: sample = sample |> put_elem(j, x) {i + 1, sample} end end {n, sample} = reduce(collection, {0, sample}, reducer) sample |> Tuple.to_list |> take(Kernel.min(count, n)) end def random(_collection, 0), do: [] @doc """ Applies the given function to each element in the collection, storing the result in a list and passing it as the accumulator for the next computation. ## Examples iex> Enum.scan(1..5, &(&1 + &2)) [1, 3, 6, 10, 15] """ @spec scan(t, (element, any -> any)) :: list def scan(enum, fun) do {res, _} = reduce(enum, {[], :first}, R.scan_2(fun)) :lists.reverse(res) end @doc """ Applies the given function to each element in the collection, storing the result in a list and passing it as the accumulator for the next computation. Uses the given `acc` as the starting value. ## Examples iex> Enum.scan(1..5, 0, &(&1 + &2)) [1, 3, 6, 10, 15] """ @spec scan(t, any, (element, any -> any)) :: list def scan(enum, acc, fun) do {res, _} = reduce(enum, {[], acc}, R.scan_3(fun)) :lists.reverse(res) end @doc """ Returns a list of collection elements shuffled. Notice that you need to explicitly call `:random.seed/1` and set a seed value for the random algorithm. Otherwise, the default seed will be set which will always return the same result. For example, one could do the following to set a seed dynamically: :random.seed(:os.timestamp) ## Examples iex> Enum.shuffle([1, 2, 3]) [3, 2, 1] iex> Enum.shuffle([1, 2, 3]) [3, 1, 2] """ @spec shuffle(t) :: list def shuffle(collection) do randomized = reduce(collection, [], fn x, acc -> [{:random.uniform, x}|acc] end) unwrap(:lists.keysort(1, randomized), []) end @doc """ Returns a subset list of the given collection. Drops elements until element position `start`, then takes `count` elements. If the count is greater than collection length, it returns as much as possible. If zero, then it returns `[]`. ## Examples iex> Enum.slice(1..100, 5, 10) [6, 7, 8, 9, 10, 11, 12, 13, 14, 15] iex> Enum.slice(1..10, 5, 100) [6, 7, 8, 9, 10] iex> Enum.slice(1..10, 5, 0) [] """ @spec slice(t, integer, non_neg_integer) :: list def slice(_collection, _start, 0), do: [] def slice(collection, start, count) when start < 0 do {list, new_start} = enumerate_and_count(collection, start) if new_start >= 0 do slice(list, new_start, count) else [] end end def slice(collection, start, count) when is_list(collection) and start >= 0 and count > 0 do do_slice(collection, start, count) end def slice(collection, start, count) when start >= 0 and count > 0 do {_, _, list} = Enumerable.reduce(collection, {:cont, {start, count, []}}, fn _entry, {start, count, _list} when start > 0 -> {:cont, {start-1, count, []}} entry, {start, count, list} when count > 1 -> {:cont, {start, count-1, [entry|list]}} entry, {start, count, list} -> {:halt, {start, count, [entry|list]}} end) |> elem(1) :lists.reverse(list) end @doc """ Returns a subset list of the given collection. Drops elements until element position `range.first`, then takes elements until element position `range.last` (inclusive). Positions are calculated by adding the number of items in the collection to negative positions (so position -3 in a collection with count 5 becomes position 2). The first position (after adding count to negative positions) must be smaller or equal to the last position. If the start of the range is not a valid offset for the given collection or if the range is in reverse order, returns `[]`. ## Examples iex> Enum.slice(1..100, 5..10) [6, 7, 8, 9, 10, 11] iex> Enum.slice(1..10, 5..20) [6, 7, 8, 9, 10] iex> Enum.slice(1..10, 11..20) [] iex> Enum.slice(1..10, 6..5) [] """ @spec slice(t, Range.t) :: list def slice(collection, range) def slice(collection, first..last) when first >= 0 and last >= 0 do # Simple case, which works on infinite collections if last - first >= 0 do slice(collection, first, last - first + 1) else [] end end def slice(collection, first..last) do {list, count} = enumerate_and_count(collection, 0) corr_first = if first >= 0, do: first, else: first + count corr_last = if last >= 0, do: last, else: last + count length = corr_last - corr_first + 1 if corr_first >= 0 and length > 0 do slice(list, corr_first, length) else [] end end @doc """ Sorts the collection according to Elixir's term ordering. Uses the merge sort algorithm. ## Examples iex> Enum.sort([3, 2, 1]) [1, 2, 3] """ @spec sort(t) :: list def sort(collection) when is_list(collection) do :lists.sort(collection) end def sort(collection) do sort(collection, &(&1 <= &2)) end @doc """ Sorts the collection by the given function. This function uses the merge sort algorithm. The given function must return `false` if the first argument is less than right one. ## Examples iex> Enum.sort([1, 2, 3], &(&1 > &2)) [3, 2, 1] The sorting algorithm will be stable as long as the given function returns `true` for values considered equal: iex> Enum.sort ["some", "kind", "of", "monster"], &(byte_size(&1) <= byte_size(&2)) ["of", "some", "kind", "monster"] If the function does not return `true` for equal values, the sorting is not stable and the order of equal terms may be shuffled: iex> Enum.sort ["some", "kind", "of", "monster"], &(byte_size(&1) < byte_size(&2)) ["of", "kind", "some", "monster"] """ @spec sort(t, (element, element -> boolean)) :: list def sort(collection, fun) when is_list(collection) do :lists.sort(fun, collection) end def sort(collection, fun) do reduce(collection, [], &sort_reducer(&1, &2, fun)) |> sort_terminator(fun) end @doc """ Sorts the mapped results of the `collection` according to the `sorter` function. This function maps each element of the collection using the `mapper` function. The collection is then sorted by the mapped elements using the `sorter` function, which defaults to `<=/2` `sort_by/3` differs from `sort/2` in that it only calculates the comparison value for each element in the collection once instead of once for each element in each comparison. If the same function is being called on both element, it's also more compact to use `sort_by/3`. This technique is also known as a [Schwartzian Transform](https://en.wikipedia.org/wiki/Schwartzian_transform), or the Lisp decorate-sort-undecorate idiom as the `mapper` is decorating the original `collection`, then `sorter` is sorting the decorations, and finally the `collection` is being undecorated so only the original elements remain, but now in sorted order. ## Examples Using the default `sorter` of `<=/2`: iex> Enum.sort_by ["some", "kind", "of", "monster"], &byte_size/1 ["of", "some", "kind", "monster"] Using a custom `sorter` to override the order: iex> Enum.sort_by ["some", "kind", "of", "monster"], &byte_size/1, &>=/2 ["monster", "some", "kind", "of"] """ @spec sort_by(t, (element -> mapped_element), (mapped_element, mapped_element -> boolean)) :: list when mapped_element: element def sort_by(collection, mapper, sorter \\ &<=/2) do collection |> map(&{&1, mapper.(&1)}) |> sort(&sorter.(elem(&1, 1), elem(&2, 1))) |> map(&elem(&1, 0)) end @doc """ Splits the enumerable into two collections, leaving `count` elements in the first one. If `count` is a negative number, it starts counting from the back to the beginning of the collection. Be aware that a negative `count` implies the collection will be enumerated twice: once to calculate the position, and a second time to do the actual splitting. ## Examples iex> Enum.split([1, 2, 3], 2) {[1, 2], [3]} iex> Enum.split([1, 2, 3], 10) {[1, 2, 3], []} iex> Enum.split([1, 2, 3], 0) {[], [1, 2, 3]} iex> Enum.split([1, 2, 3], -1) {[1, 2], [3]} iex> Enum.split([1, 2, 3], -5) {[], [1, 2, 3]} """ @spec split(t, integer) :: {list, list} def split(collection, count) when is_list(collection) and count >= 0 do do_split(collection, count, []) end def split(collection, count) when count >= 0 do {_, list1, list2} = reduce(collection, {count, [], []}, fn(entry, {counter, acc1, acc2}) -> if counter > 0 do {counter - 1, [entry|acc1], acc2} else {counter, acc1, [entry|acc2]} end end) {:lists.reverse(list1), :lists.reverse(list2)} end def split(collection, count) when count < 0 do do_split_reverse(reverse(collection), abs(count), []) end @doc """ Splits `collection` in two at the position of the element for which `fun` returns `false` for the first time. ## Examples iex> Enum.split_while([1, 2, 3, 4], fn(x) -> x < 3 end) {[1, 2], [3, 4]} """ @spec split_while(t, (element -> as_boolean(term))) :: {list, list} def split_while(collection, fun) when is_list(collection) do do_split_while(collection, fun, []) end def split_while(collection, fun) do {list1, list2} = reduce(collection, {[], []}, fn entry, {acc1, []} -> if(fun.(entry), do: {[entry|acc1], []}, else: {acc1, [entry]}) entry, {acc1, acc2} -> {acc1, [entry|acc2]} end) {:lists.reverse(list1), :lists.reverse(list2)} end @doc """ Takes the first `count` items from the collection. `count` must be an integer. If a negative `count` is given, the last `count` values will be taken. For such, the collection is fully enumerated keeping up to `2 * count` elements in memory. Once the end of the collection is reached, the last `count` elements are returned. ## Examples iex> Enum.take([1, 2, 3], 2) [1, 2] iex> Enum.take([1, 2, 3], 10) [1, 2, 3] iex> Enum.take([1, 2, 3], 0) [] iex> Enum.take([1, 2, 3], -1) [3] """ @spec take(t, integer) :: list def take(_collection, 0), do: [] def take([], _count), do: [] def take(collection, n) when is_list(collection) and is_integer(n) and n > 0 do do_take(collection, n) end def take(collection, n) when is_integer(n) and n > 0 do {_, {res, _}} = Enumerable.reduce(collection, {:cont, {[], n}}, fn(entry, {list, count}) -> case count do 0 -> {:halt, {list, count}} 1 -> {:halt, {[entry|list], count - 1}} _ -> {:cont, {[entry|list], count - 1}} end end) :lists.reverse(res) end def take(collection, n) when is_integer(n) and n < 0 do n = abs(n) {_count, buf1, buf2} = reduce(collection, {0, [], []}, fn entry, {count, buf1, buf2} -> buf1 = [entry|buf1] count = count + 1 if count == n do {0, [], buf1} else {count, buf1, buf2} end end) do_take_last(buf1, buf2, n, []) end defp do_take_last(_buf1, _buf2, 0, acc), do: acc defp do_take_last([], [], _, acc), do: acc defp do_take_last([], [h|t], n, acc), do: do_take_last([], t, n-1, [h|acc]) defp do_take_last([h|t], buf2, n, acc), do: do_take_last(t, buf2, n-1, [h|acc]) @doc """ Returns a collection of every `nth` item in the collection, starting with the first element. The second argument specifying every `nth` item must be a non-negative integer. ## Examples iex> Enum.take_every(1..10, 2) [1, 3, 5, 7, 9] """ @spec take_every(t, non_neg_integer) :: list def take_every(_collection, 0), do: [] def take_every([], _nth), do: [] def take_every(collection, nth) when is_integer(nth) and nth > 0 do {res, _} = reduce(collection, {[], :first}, R.take_every(nth)) :lists.reverse(res) end @doc """ Takes the items from the beginning of `collection` while `fun` returns a truthy value. ## Examples iex> Enum.take_while([1, 2, 3], fn(x) -> x < 3 end) [1, 2] """ @spec take_while(t, (element -> as_boolean(term))) :: list def take_while(collection, fun) when is_list(collection) do do_take_while(collection, fun) end def take_while(collection, fun) do {_, res} = Enumerable.reduce(collection, {:cont, []}, fn(entry, acc) -> if fun.(entry) do {:cont, [entry|acc]} else {:halt, acc} end end) :lists.reverse(res) end @doc """ Converts `collection` to a list. ## Examples iex> Enum.to_list(1 .. 3) [1, 2, 3] """ @spec to_list(t) :: [term] def to_list(collection) when is_list(collection) do collection end def to_list(collection) do reverse(collection) |> :lists.reverse end @doc """ Enumerates the collection, removing all duplicated elements. ## Examples iex> Enum.uniq([1, 2, 3, 3, 2, 1]) |> Enum.to_list [1, 2, 3] """ @spec uniq(t) :: list def uniq(collection) do uniq_by(collection, fn x -> x end) end # TODO: Deprecate by 1.2 # TODO: Remove by 2.0 @doc false def uniq(collection, fun) do uniq_by(collection, fun) end @doc """ Enumerates the collection, removing all duplicated elements. ## Example iex> Enum.uniq_by([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end) [{1, :x}, {2, :y}] """ @spec uniq_by(t, (element -> term)) :: list def uniq_by(collection, fun) when is_list(collection) do do_uniq(collection, HashSet.new, fun) end def uniq_by(collection, fun) do {list, _} = reduce(collection, {[], HashSet.new}, R.uniq(fun)) :lists.reverse(list) end @doc """ Opposite of `Enum.zip/2`; takes a list of two-element tuples and returns a tuple with two lists, each of which is formed by the first and second element of each tuple, respectively. This function fails unless `collection` is or can be converted into a list of tuples with *exactly* two elements in each tuple. ## Examples iex> Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}]) {[:a, :b, :c], [1, 2, 3]} iex> Enum.unzip(%{a: 1, b: 2}) {[:a, :b], [1, 2]} """ @spec unzip(t) :: {list(element), list(element)} def unzip(collection) do {list1, list2} = reduce(collection, {[], []}, fn({el1, el2}, {list1, list2}) -> {[el1|list1], [el2|list2]} end) {:lists.reverse(list1), :lists.reverse(list2)} end @doc """ Zips corresponding elements from two collections into one list of tuples. The zipping finishes as soon as any enumerable completes. ## Examples iex> Enum.zip([1, 2, 3], [:a, :b, :c]) [{1, :a}, {2, :b}, {3, :c}] iex> Enum.zip([1, 2, 3, 4, 5], [:a, :b, :c]) [{1, :a}, {2, :b}, {3, :c}] """ @spec zip(t, t) :: [{any, any}] def zip(collection1, collection2) when is_list(collection1) and is_list(collection2) do do_zip(collection1, collection2) end def zip(collection1, collection2) do Stream.zip(collection1, collection2).({:cont, []}, &{:cont, [&1|&2]}) |> elem(1) |> :lists.reverse end @doc """ Returns the collection with each element wrapped in a tuple alongside its index. ## Examples iex> Enum.with_index [1, 2, 3] [{1, 0}, {2, 1}, {3, 2}] """ @spec with_index(t) :: list({element, non_neg_integer}) def with_index(collection) do map_reduce(collection, 0, fn x, acc -> {{x, acc}, acc + 1} end) |> elem(0) end ## Helpers @compile {:inline, enum_to_string: 1} defp enumerate_and_count(collection, count) when is_list(collection) do {collection, length(collection) - abs(count)} end defp enumerate_and_count(collection, count) do map_reduce(collection, -abs(count), fn(x, acc) -> {x, acc + 1} end) end defp enum_to_string(entry) when is_binary(entry), do: entry defp enum_to_string(entry), do: String.Chars.to_string(entry) defp random_index(n) do :random.uniform(n + 1) - 1 end ## Implementations ## all? defp do_all?([h|t], fun) do if fun.(h) do do_all?(t, fun) else false end end defp do_all?([], _) do true end ## any? defp do_any?([h|t], fun) do if fun.(h) do true else do_any?(t, fun) end end defp do_any?([], _) do false end ## fetch defp do_fetch([h|_], 0), do: {:ok, h} defp do_fetch([_|t], n), do: do_fetch(t, n - 1) defp do_fetch([], _), do: :error ## drop defp do_drop([_|t], counter) when counter > 0 do do_drop(t, counter - 1) end defp do_drop(list, 0) do list end defp do_drop([], _) do [] end ## drop_while defp do_drop_while([h|t], fun) do if fun.(h) do do_drop_while(t, fun) else [h|t] end end defp do_drop_while([], _) do [] end ## find defp do_find([h|t], ifnone, fun) do if fun.(h) do h else do_find(t, ifnone, fun) end end defp do_find([], ifnone, _) do ifnone end ## find_index defp do_find_index([h|t], counter, fun) do if fun.(h) do counter else do_find_index(t, counter + 1, fun) end end defp do_find_index([], _, _) do nil end ## find_value defp do_find_value([h|t], ifnone, fun) do fun.(h) || do_find_value(t, ifnone, fun) end defp do_find_value([], ifnone, _) do ifnone end ## shuffle defp unwrap([{_, h} | collection], t) do unwrap(collection, [h|t]) end defp unwrap([], t), do: t ## sort defp sort_reducer(entry, {:split, y, x, r, rs, bool}, fun) do cond do fun.(y, entry) == bool -> {:split, entry, y, [x|r], rs, bool} fun.(x, entry) == bool -> {:split, y, entry, [x|r], rs, bool} r == [] -> {:split, y, x, [entry], rs, bool} true -> {:pivot, y, x, r, rs, entry, bool} end end defp sort_reducer(entry, {:pivot, y, x, r, rs, s, bool}, fun) do cond do fun.(y, entry) == bool -> {:pivot, entry, y, [x | r], rs, s, bool} fun.(x, entry) == bool -> {:pivot, y, entry, [x | r], rs, s, bool} fun.(s, entry) == bool -> {:split, entry, s, [], [[y, x | r] | rs], bool} true -> {:split, s, entry, [], [[y, x | r] | rs], bool} end end defp sort_reducer(entry, [x], fun) do {:split, entry, x, [], [], fun.(x, entry)} end defp sort_reducer(entry, acc, _fun) do [entry|acc] end defp sort_terminator({:split, y, x, r, rs, bool}, fun) do sort_merge([[y, x | r] | rs], fun, bool) end defp sort_terminator({:pivot, y, x, r, rs, s, bool}, fun) do sort_merge([[s], [y, x | r] | rs], fun, bool) end defp sort_terminator(acc, _fun) do acc end defp sort_merge(list, fun, true), do: reverse_sort_merge(list, [], fun, true) defp sort_merge(list, fun, false), do: sort_merge(list, [], fun, false) defp sort_merge([t1, [h2 | t2] | l], acc, fun, true), do: sort_merge(l, [sort_merge_1(t1, h2, t2, [], fun, false) | acc], fun, true) defp sort_merge([[h2 | t2], t1 | l], acc, fun, false), do: sort_merge(l, [sort_merge_1(t1, h2, t2, [], fun, false) | acc], fun, false) defp sort_merge([l], [], _fun, _bool), do: l defp sort_merge([l], acc, fun, bool), do: reverse_sort_merge([:lists.reverse(l, []) | acc], [], fun, bool) defp sort_merge([], acc, fun, bool), do: reverse_sort_merge(acc, [], fun, bool) defp reverse_sort_merge([[h2 | t2], t1 | l], acc, fun, true), do: reverse_sort_merge(l, [sort_merge_1(t1, h2, t2, [], fun, true) | acc], fun, true) defp reverse_sort_merge([t1, [h2 | t2] | l], acc, fun, false), do: reverse_sort_merge(l, [sort_merge_1(t1, h2, t2, [], fun, true) | acc], fun, false) defp reverse_sort_merge([l], acc, fun, bool), do: sort_merge([:lists.reverse(l, []) | acc], [], fun, bool) defp reverse_sort_merge([], acc, fun, bool), do: sort_merge(acc, [], fun, bool) defp sort_merge_1([h1 | t1], h2, t2, m, fun, bool) do if fun.(h1, h2) == bool do sort_merge_2(h1, t1, t2, [h2 | m], fun, bool) else sort_merge_1(t1, h2, t2, [h1 | m], fun, bool) end end defp sort_merge_1([], h2, t2, m, _fun, _bool), do: :lists.reverse(t2, [h2 | m]) defp sort_merge_2(h1, t1, [h2 | t2], m, fun, bool) do if fun.(h1, h2) == bool do sort_merge_2(h1, t1, t2, [h2 | m], fun, bool) else sort_merge_1(t1, h2, t2, [h1 | m], fun, bool) end end defp sort_merge_2(h1, t1, [], m, _fun, _bool), do: :lists.reverse(t1, [h1 | m]) ## reverse_slice defp reverse_slice(rest, idx, idx, count, acc) do {slice, rest} = head_slice(rest, count, []) :lists.reverse(rest, :lists.reverse(slice, acc)) end defp reverse_slice([elem | rest], idx, start, count, acc) do reverse_slice(rest, idx - 1, start, count, [elem | acc]) end defp head_slice(rest, 0, acc), do: {acc, rest} defp head_slice([elem | rest], count, acc) do head_slice(rest, count - 1, [elem | acc]) end ## split defp do_split([h|t], counter, acc) when counter > 0 do do_split(t, counter - 1, [h|acc]) end defp do_split(list, 0, acc) do {:lists.reverse(acc), list} end defp do_split([], _, acc) do {:lists.reverse(acc), []} end defp do_split_reverse([h|t], counter, acc) when counter > 0 do do_split_reverse(t, counter - 1, [h|acc]) end defp do_split_reverse(list, 0, acc) do {:lists.reverse(list), acc} end defp do_split_reverse([], _, acc) do {[], acc} end ## split_while defp do_split_while([h|t], fun, acc) do if fun.(h) do do_split_while(t, fun, [h|acc]) else {:lists.reverse(acc), [h|t]} end end defp do_split_while([], _, acc) do {:lists.reverse(acc), []} end ## take defp do_take([h|t], counter) when counter > 0 do [h|do_take(t, counter - 1)] end defp do_take(_list, 0) do [] end defp do_take([], _) do [] end ## take_while defp do_take_while([h|t], fun) do if fun.(h) do [h|do_take_while(t, fun)] else [] end end defp do_take_while([], _) do [] end ## uniq defp do_uniq([h|t], acc, fun) do fun_h = fun.(h) if HashSet.member?(acc, fun_h) do do_uniq(t, acc, fun) else [h|do_uniq(t, HashSet.put(acc, fun_h), fun)] end end defp do_uniq([], _acc, _fun) do [] end ## zip defp do_zip([h1|next1], [h2|next2]) do [{h1, h2}|do_zip(next1, next2)] end defp do_zip(_, []), do: [] defp do_zip([], _), do: [] ## slice defp do_slice([], _start, _count) do [] end defp do_slice(_list, _start, 0) do [] end defp do_slice([h|t], 0, count) do [h|do_slice(t, 0, count-1)] end defp do_slice([_|t], start, count) do do_slice(t, start-1, count) end end defimpl Enumerable, for: List do def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)} def reduce([], {:cont, acc}, _fun), do: {:done, acc} def reduce([h|t], {:cont, acc}, fun), do: reduce(t, fun.(h, acc), fun) def member?(_list, _value), do: {:error, __MODULE__} def count(_list), do: {:error, __MODULE__} end defimpl Enumerable, for: Map do def reduce(map, acc, fun) do do_reduce(:maps.to_list(map), acc, fun) end defp do_reduce(_, {:halt, acc}, _fun), do: {:halted, acc} defp do_reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &do_reduce(list, &1, fun)} defp do_reduce([], {:cont, acc}, _fun), do: {:done, acc} defp do_reduce([h|t], {:cont, acc}, fun), do: do_reduce(t, fun.(h, acc), fun) def member?(map, {key, value}) do {:ok, match?({:ok, ^value}, :maps.find(key, map))} end def member?(_map, _other) do {:ok, false} end def count(map) do {:ok, map_size(map)} end end defimpl Enumerable, for: Function do def reduce(function, acc, fun) when is_function(function, 2), do: function.(acc, fun) def member?(_function, _value), do: {:error, __MODULE__} def count(_function), do: {:error, __MODULE__} end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/exception.ex000066400000000000000000000553761254730255300223010ustar00rootroot00000000000000defmodule Exception do @moduledoc """ Functions to format throw/catch/exit and exceptions. Note that stacktraces in Elixir are updated on throw, errors and exits. For example, at any given moment, `System.stacktrace` will return the stacktrace for the last throw/error/exit that occurred in the current process. Do not rely on the particular format returned by the `format` functions in this module. They may be changed in future releases in order to better suit Elixir's tool chain. In other words, by using the functions in this module it is guaranteed you will format exceptions as in the current Elixir version being used. """ @typedoc "The exception type" @type t :: %{__struct__: module, __exception__: true} @typedoc "The kind handled by formatting functions" @type kind :: :error | :exit | :throw | {:EXIT, pid} @type stacktrace :: [stacktrace_entry] @type stacktrace_entry :: {module, atom, arity_or_args, location} | {(... -> any), arity_or_args, location} @typep arity_or_args :: non_neg_integer | list @typep location :: Keyword.t use Behaviour defcallback exception(term) :: t defcallback message(t) :: String.t @doc """ Returns `true` if the given `term` is an exception. """ def exception?(term) def exception?(%{__struct__: struct, __exception__: true}) when is_atom(struct), do: true def exception?(_), do: false @doc """ Gets the message for an exception. """ def message(%{__struct__: module, __exception__: true} = exception) when is_atom(module) do try do module.message(exception) rescue e -> "got #{inspect e.__struct__} with message `#{message(e)}` " <> "while retrieving Exception.message/1 for #{inspect(exception)}" else x when is_binary(x) -> x x -> "got #{inspect(x)} while retrieving Exception.message/1 for #{inspect(exception)} " <> "(expected a string)" end end @doc """ Normalizes an exception, converting Erlang exceptions to Elixir exceptions. It takes the `kind` spilled by `catch` as an argument and normalizes only `:error`, returning the untouched payload for others. The third argument, a stacktrace, is optional. If it is not supplied `System.stacktrace/0` will sometimes be used to get additional information for the `kind` `:error`. If the stacktrace is unknown and `System.stacktrace/0` would not return the stacktrace corresponding to the exception an empty stacktrace, `[]`, must be used. """ @spec normalize(:error, any, stacktrace) :: t @spec normalize(kind, payload, stacktrace) :: payload when payload: var # Generating a stacktrace is expensive, default to nil # to only fetch it when needed. def normalize(kind, payload, stacktrace \\ nil) def normalize(:error, exception, stacktrace) do if exception?(exception) do exception else ErlangError.normalize(exception, stacktrace) end end def normalize(_kind, payload, _stacktrace) do payload end @doc """ Normalizes and formats any throw, error and exit. The message is formatted and displayed in the same format as used by Elixir's CLI. The third argument, a stacktrace, is optional. If it is not supplied `System.stacktrace/0` will sometimes be used to get additional information for the `kind` `:error`. If the stacktrace is unknown and `System.stacktrace/0` would not return the stacktrace corresponding to the exception an empty stacktrace, `[]`, must be used. """ @spec format_banner(kind, any, stacktrace | nil) :: String.t def format_banner(kind, exception, stacktrace \\ nil) def format_banner(:error, exception, stacktrace) do exception = normalize(:error, exception, stacktrace) "** (" <> inspect(exception.__struct__) <> ") " <> message(exception) end def format_banner(:throw, reason, _stacktrace) do "** (throw) " <> inspect(reason) end def format_banner(:exit, reason, _stacktrace) do "** (exit) " <> format_exit(reason, <<"\n ">>) end def format_banner({:EXIT, pid}, reason, _stacktrace) do "** (EXIT from #{inspect pid}) " <> format_exit(reason, <<"\n ">>) end @doc """ Normalizes and formats throw/errors/exits and stacktrace. It relies on `format_banner/3` and `format_stacktrace/1` to generate the final format. Note that `{:EXIT, pid}` do not generate a stacktrace though (as they are retrieved as messages without stacktraces). """ @spec format(kind, any, stacktrace | nil) :: String.t def format(kind, payload, stacktrace \\ nil) def format({:EXIT, _} = kind, any, _) do format_banner(kind, any) end def format(kind, payload, stacktrace) do stacktrace = stacktrace || System.stacktrace message = format_banner(kind, payload, stacktrace) case stacktrace do [] -> message _ -> message <> "\n" <> format_stacktrace(stacktrace) end end @doc """ Formats an exit, returns a string. Often there are errors/exceptions inside exits. Exits are often wrapped by the caller and provide stacktraces too. This function formats exits in a way to nicely show the exit reason, caller and stacktrace. """ @spec format_exit(any) :: String.t def format_exit(reason) do format_exit(reason, <<"\n ">>) end # 2-Tuple could be caused by an error if the second element is a stacktrace. defp format_exit({exception, maybe_stacktrace} = reason, joiner) when is_list(maybe_stacktrace) and maybe_stacktrace !== [] do try do Enum.map(maybe_stacktrace, &format_stacktrace_entry/1) else formatted_stacktrace -> # Assume a non-empty list formattable as stacktrace is a # stacktrace, so exit was caused by an error. message = "an exception was raised:" <> joiner <> format_banner(:error, exception, maybe_stacktrace) Enum.join([message | formatted_stacktrace], joiner <> <<" ">>) catch :error, _ -> # Not a stacktrace, was an exit. format_exit_reason(reason) end end # :supervisor.start_link returns this error reason when it fails to init # because a child's start_link raises. defp format_exit({:shutdown, {:failed_to_start_child, child, {:EXIT, reason}}}, joiner) do format_start_child(child, reason, joiner) end # :supervisor.start_link returns this error reason when it fails to init # because a child's start_link returns {:error, reason}. defp format_exit({:shutdown, {:failed_to_start_child, child, reason}}, joiner) do format_start_child(child, reason, joiner) end # 2-Tuple could be an exit caused by mfa if second element is mfa, args # must be a list of arguments - max length 255 due to max arity. defp format_exit({reason2, {mod, fun, args}} = reason, joiner) when length(args) < 256 do try do format_mfa(mod, fun, args) else mfa -> # Assume tuple formattable as an mfa is an mfa, so exit was caused by # failed mfa. "exited in: " <> mfa <> joiner <> "** (EXIT) " <> format_exit(reason2, joiner <> <<" ">>) catch :error, _ -> # Not an mfa, was an exit. format_exit_reason(reason) end end defp format_exit(reason, _joiner) do format_exit_reason(reason) end defp format_exit_reason(:normal), do: "normal" defp format_exit_reason(:shutdown), do: "shutdown" defp format_exit_reason({:shutdown, reason}) do "shutdown: #{inspect(reason)}" end defp format_exit_reason(:timeout), do: "time out" defp format_exit_reason(:killed), do: "killed" defp format_exit_reason(:noconnection), do: "no connection" defp format_exit_reason(:noproc) do "no process" end defp format_exit_reason({:nodedown, node_name}) when is_atom(node_name) do "no connection to #{node_name}" end # :gen_server exit reasons defp format_exit_reason({:already_started, pid}) do "already started: " <> inspect(pid) end defp format_exit_reason({:bad_return_value, value}) do "bad return value: " <> inspect(value) end defp format_exit_reason({:bad_call, request}) do "bad call: " <> inspect(request) end defp format_exit_reason({:bad_cast, request}) do "bad cast: " <> inspect(request) end # :supervisor.start_link error reasons # If value is a list will be formatted by mfa exit in format_exit/1 defp format_exit_reason({:bad_return, {mod, :init, value}}) when is_atom(mod) do format_mfa(mod, :init, 1) <> " returned a bad value: " <> inspect(value) end defp format_exit_reason({:bad_start_spec, start_spec}) do "bad start spec: invalid children: " <> inspect(start_spec) end defp format_exit_reason({:start_spec, start_spec}) do "bad start spec: " <> format_sup_spec(start_spec) end defp format_exit_reason({:supervisor_data, data}) do "bad supervisor data: " <> format_sup_data(data) end defp format_exit_reason(reason), do: inspect(reason) defp format_start_child(child, reason, joiner) do "shutdown: failed to start child: " <> inspect(child) <> joiner <> "** (EXIT) " <> format_exit(reason, joiner <> <<" ">>) end defp format_sup_data({:invalid_type, type}) do "invalid type: " <> inspect(type) end defp format_sup_data({:invalid_strategy, strategy}) do "invalid strategy: " <> inspect(strategy) end defp format_sup_data({:invalid_intensity, intensity}) do "invalid intensity: " <> inspect(intensity) end defp format_sup_data({:invalid_period, period}) do "invalid period: " <> inspect(period) end defp format_sup_data(other), do: inspect(other) defp format_sup_spec({:invalid_child_spec, child_spec}) do "invalid child spec: " <> inspect(child_spec) end defp format_sup_spec({:invalid_child_type, type}) do "invalid child type: " <> inspect(type) end defp format_sup_spec({:invalid_mfa, mfa}) do "invalid mfa: " <> inspect(mfa) end defp format_sup_spec({:invalid_restart_type, restart}) do "invalid restart type: " <> inspect(restart) end defp format_sup_spec({:invalid_shutdown, shutdown}) do "invalid shutdown: " <> inspect(shutdown) end defp format_sup_spec({:invalid_module, mod}) do "invalid module: " <> inspect(mod) end defp format_sup_spec({:invalid_modules, modules}) do "invalid modules: " <> inspect(modules) end defp format_sup_spec(other), do: inspect(other) @doc """ Receives a stacktrace entry and formats it into a string. """ @spec format_stacktrace_entry(stacktrace_entry) :: String.t def format_stacktrace_entry(entry) # From Macro.Env.stacktrace def format_stacktrace_entry({module, :__MODULE__, 0, location}) do format_location(location) <> inspect(module) <> " (module)" end # From :elixir_compiler_* def format_stacktrace_entry({_module, :__MODULE__, 1, location}) do format_location(location) <> "(module)" end # From :elixir_compiler_* def format_stacktrace_entry({_module, :__FILE__, 1, location}) do format_location(location) <> "(file)" end def format_stacktrace_entry({module, fun, arity, location}) do format_application(module) <> format_location(location) <> format_mfa(module, fun, arity) end def format_stacktrace_entry({fun, arity, location}) do format_location(location) <> format_fa(fun, arity) end defp format_application(module) do case :application.get_application(module) do {:ok, app} -> "(" <> Atom.to_string(app) <> ") " :undefined -> "" end end @doc """ Formats the stacktrace. A stacktrace must be given as an argument. If not, the stacktrace is retrieved from `Process.info/2`. """ def format_stacktrace(trace \\ nil) do trace = trace || case Process.info(self, :current_stacktrace) do {:current_stacktrace, t} -> Enum.drop(t, 3) end case trace do [] -> "\n" s -> " " <> Enum.map_join(s, "\n ", &format_stacktrace_entry(&1)) <> "\n" end end @doc """ Receives an anonymous function and arity and formats it as shown in stacktraces. The arity may also be a list of arguments. ## Examples Exception.format_fa(fn -> end, 1) #=> "#Function<...>/1" """ def format_fa(fun, arity) when is_function(fun) do "#{inspect fun}#{format_arity(arity)}" end @doc """ Receives a module, fun and arity and formats it as shown in stacktraces. The arity may also be a list of arguments. ## Examples iex> Exception.format_mfa Foo, :bar, 1 "Foo.bar/1" iex> Exception.format_mfa Foo, :bar, [] "Foo.bar()" iex> Exception.format_mfa nil, :bar, [] "nil.bar()" Anonymous functions are reported as -func/arity-anonfn-count-, where func is the name of the enclosing function. Convert to "anonymous fn in func/arity" """ def format_mfa(module, fun, arity) when is_atom(module) and is_atom(fun) do fun = case inspect(fun) do ":" <> fun -> fun fun -> fun end case match?("\"-" <> _, fun) and String.split(fun, "-") do [ "\"", outer_fun, "fun", _count, "\"" ] -> "anonymous fn#{format_arity(arity)} in #{inspect module}.#{outer_fun}" _ -> "#{inspect module}.#{fun}#{format_arity(arity)}" end end defp format_arity(arity) when is_list(arity) do inspected = for x <- arity, do: inspect(x) "(#{Enum.join(inspected, ", ")})" end defp format_arity(arity) when is_integer(arity) do "/" <> Integer.to_string(arity) end @doc """ Formats the given file and line as shown in stacktraces. If any of the values are `nil`, they are omitted. ## Examples iex> Exception.format_file_line("foo", 1) "foo:1:" iex> Exception.format_file_line("foo", nil) "foo:" iex> Exception.format_file_line(nil, nil) "" """ def format_file_line(file, line) do format_file_line(file, line, "") end defp format_file_line(file, line, suffix) do if file do if line && line != 0 do "#{file}:#{line}:#{suffix}" else "#{file}:#{suffix}" end else "" end end defp format_location(opts) when is_list(opts) do format_file_line Keyword.get(opts, :file), Keyword.get(opts, :line), " " end end # Some exceptions implement `message/1` instead of `exception/1` mostly # for bootstrap reasons. It is recommended for applications to implement # `exception/1` instead of `message/1` as described in `defexception/1` # docs. defmodule RuntimeError do defexception message: "runtime error" end defmodule ArgumentError do defexception message: "argument error" end defmodule ArithmeticError do defexception [] def message(_) do "bad argument in arithmetic expression" end end defmodule SystemLimitError do defexception [] def message(_) do "a system limit has been reached" end end defmodule SyntaxError do defexception [file: nil, line: nil, description: "syntax error"] def message(exception) do Exception.format_file_line(Path.relative_to_cwd(exception.file), exception.line) <> " " <> exception.description end end defmodule TokenMissingError do defexception [file: nil, line: nil, description: "expression is incomplete"] def message(exception) do Exception.format_file_line(Path.relative_to_cwd(exception.file), exception.line) <> " " <> exception.description end end defmodule CompileError do defexception [file: nil, line: nil, description: "compile error"] def message(exception) do Exception.format_file_line(Path.relative_to_cwd(exception.file), exception.line) <> " " <> exception.description end end defmodule BadFunctionError do defexception [term: nil] def message(exception) do "expected a function, got: #{inspect(exception.term)}" end end defmodule BadStructError do defexception [struct: nil, term: nil] def message(exception) do "expected a struct named #{inspect(exception.struct)}, got: #{inspect(exception.term)}" end end defmodule BadMapError do defexception [term: nil] def message(exception) do "expected a map, got: #{inspect(exception.term)}" end end defmodule MatchError do defexception [term: nil] def message(exception) do "no match of right hand side value: #{inspect(exception.term)}" end end defmodule CaseClauseError do defexception [term: nil] def message(exception) do "no case clause matching: #{inspect(exception.term)}" end end defmodule CondClauseError do defexception [] def message(_exception) do "no cond clause evaluated to a true value" end end defmodule TryClauseError do defexception [term: nil] def message(exception) do "no try clause matching: #{inspect(exception.term)}" end end defmodule BadArityError do defexception [function: nil, args: nil] def message(exception) do fun = exception.function args = exception.args insp = Enum.map_join(args, ", ", &inspect/1) {:arity, arity} = :erlang.fun_info(fun, :arity) "#{inspect(fun)} with arity #{arity} called with #{count(length(args), insp)}" end defp count(0, _insp), do: "no arguments" defp count(1, insp), do: "1 argument (#{insp})" defp count(x, insp), do: "#{x} arguments (#{insp})" end defmodule UndefinedFunctionError do defexception [module: nil, function: nil, arity: nil, reason: nil] def message(%{reason: nil, module: module, function: function, arity: arity} = e) do cond do is_nil(function) or is_nil(arity) -> "undefined function" not is_nil(module) and :code.is_loaded(module) === false -> message(%{e | reason: :"module could not be loaded"}) true -> message(%{e | reason: :"function not exported"}) end end def message(%{reason: :"module could not be loaded", module: module, function: function, arity: arity}) do "undefined function: " <> Exception.format_mfa(module, function, arity) <> " (module #{inspect module} is not available)" end def message(%{reason: :"function not exported", module: module, function: function, arity: arity}) do "undefined function: " <> Exception.format_mfa(module, function, arity) end def message(%{reason: :"function not available", module: module, function: function, arity: arity}) do "nil." <> fa = Exception.format_mfa(nil, function, arity) "undefined function: " <> Exception.format_mfa(module, function, arity) <> " (function #{fa} is not available)" end end defmodule FunctionClauseError do defexception [module: nil, function: nil, arity: nil] def message(exception) do if exception.function do formatted = Exception.format_mfa exception.module, exception.function, exception.arity "no function clause matching in #{formatted}" else "no function clause matches" end end end defmodule Code.LoadError do defexception [:file, :message] def exception(opts) do file = Keyword.fetch!(opts, :file) %Code.LoadError{message: "could not load #{file}", file: file} end end defmodule Protocol.UndefinedError do defexception [protocol: nil, value: nil, description: nil] def message(exception) do msg = "protocol #{inspect exception.protocol} not implemented for #{inspect exception.value}" if exception.description do msg <> ", " <> exception.description else msg end end end defmodule KeyError do defexception key: nil, term: nil def message(exception) do msg = "key #{inspect exception.key} not found" if exception.term != nil do msg <> " in: #{inspect exception.term}" else msg end end end defmodule UnicodeConversionError do defexception [:encoded, :message] def exception(opts) do %UnicodeConversionError{ encoded: Keyword.fetch!(opts, :encoded), message: "#{Keyword.fetch!(opts, :kind)} #{detail Keyword.fetch!(opts, :rest)}" } end defp detail(rest) when is_binary(rest) do "encoding starting at #{inspect rest}" end defp detail([h|_]) do "code point #{h}" end end defmodule Enum.OutOfBoundsError do defexception [] def message(_) do "out of bounds error" end end defmodule Enum.EmptyError do defexception [] def message(_) do "empty error" end end defmodule File.Error do defexception [reason: nil, action: "", path: nil] def message(exception) do formatted = IO.iodata_to_binary(:file.format_error(exception.reason)) "could not #{exception.action} #{exception.path}: #{formatted}" end end defmodule File.CopyError do defexception [reason: nil, action: "", source: nil, destination: nil, on: nil] def message(exception) do formatted = IO.iodata_to_binary(:file.format_error(exception.reason)) location = if on = exception.on, do: ". #{on}", else: "" "could not #{exception.action} from #{exception.source} to " <> "#{exception.destination}#{location}: #{formatted}" end end defmodule ErlangError do defexception [original: nil] def message(exception) do "erlang error: #{inspect(exception.original)}" end @doc false def normalize(:badarg, _stacktrace) do %ArgumentError{} end def normalize(:badarith, _stacktrace) do %ArithmeticError{} end def normalize(:system_limit, _stacktrace) do %SystemLimitError{} end def normalize(:cond_clause, _stacktrace) do %CondClauseError{} end def normalize({:badarity, {fun, args}}, _stacktrace) do %BadArityError{function: fun, args: args} end def normalize({:badfun, term}, _stacktrace) do %BadFunctionError{term: term} end def normalize({:badstruct, struct, term}, _stacktrace) do %BadStructError{struct: struct, term: term} end def normalize({:badmatch, term}, _stacktrace) do %MatchError{term: term} end def normalize({:badmap, term}, _stacktrace) do %BadMapError{term: term} end def normalize({:badkey, key}, stacktrace) do term = case stacktrace || :erlang.get_stacktrace do [{:maps, :update, [_, _, map], _}|_] -> map [{:maps, :get, [_, map], _}|_] -> map _ -> nil end %KeyError{key: key, term: term} end def normalize({:case_clause, term}, _stacktrace) do %CaseClauseError{term: term} end def normalize({:try_clause, term}, _stacktrace) do %TryClauseError{term: term} end def normalize(:undef, stacktrace) do stacktrace = stacktrace || :erlang.get_stacktrace {mod, fun, arity} = from_stacktrace(stacktrace) %UndefinedFunctionError{module: mod, function: fun, arity: arity} end def normalize(:function_clause, stacktrace) do {mod, fun, arity} = from_stacktrace(stacktrace || :erlang.get_stacktrace) %FunctionClauseError{module: mod, function: fun, arity: arity} end def normalize({:badarg, payload}, _stacktrace) do %ArgumentError{message: "argument error: #{inspect(payload)}"} end def normalize(other, _stacktrace) do %ErlangError{original: other} end defp from_stacktrace([{module, function, args, _}|_]) when is_list(args) do {module, function, length(args)} end defp from_stacktrace([{module, function, arity, _}|_]) do {module, function, arity} end defp from_stacktrace(_) do {nil, nil, nil} end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/file.ex000066400000000000000000001175521254730255300212150ustar00rootroot00000000000000defmodule File do @moduledoc ~S""" This module contains functions to manipulate files. Some of those functions are low-level, allowing the user to interact with the file or IO devices, like `open/2`, `copy/3` and others. This module also provides higher level functions that work with filenames and have their naming based on UNIX variants. For example, one can copy a file via `cp/3` and remove files and directories recursively via `rm_rf/1` ## Encoding In order to write and read files, one must use the functions in the `IO` module. By default, a file is opened in binary mode which requires the functions `IO.binread/2` and `IO.binwrite/2` to interact with the file. A developer may pass `:utf8` as an option when opening the file, then the slower `IO.read/2` and `IO.write/2` functions must be used as they are responsible for doing the proper conversions and data guarantees. Note that filenames when given as char lists in Elixir are always treated as UTF-8. In particular, we expect that the shell and the operating system are configured to use UTF8 encoding. Binary filenames are considering raw and passed to the OS as is. ## API Most of the functions in this module return `:ok` or `{:ok, result}` in case of success, `{:error, reason}` otherwise. Those function are also followed by a variant that ends with `!` which returns the result (without the `{:ok, result}` tuple) in case of success or raises an exception in case it fails. For example: File.read("hello.txt") #=> {:ok, "World"} File.read("invalid.txt") #=> {:error, :enoent} File.read!("hello.txt") #=> "World" File.read!("invalid.txt") #=> raises File.Error In general, a developer should use the former in case they want to react if the file does not exist. The latter should be used when the developer expects their software to fail in case the file cannot be read (i.e. it is literally an exception). ## Processes and raw files Every time a file is opened, Elixir spawns a new process. Writing to a file is equivalent to sending messages to that process that writes to the file descriptor. This means files can be passed between nodes and message passing guarantees they can write to the same file in a network. However, you may not always want to pay the price for this abstraction. In such cases, a file can be opened in `:raw` mode. The options `:read_ahead` and `:delayed_write` are also useful when operating large files or working with files in tight loops. Check http://www.erlang.org/doc/man/file.html#open-2 for more information about such options and other performance considerations. """ alias :file, as: F @type posix :: :file.posix() @type io_device :: :file.io_device() @type stat_options :: [time: :local | :universal | :posix] @type mode :: :append | :binary | :compressed | :delayed_write | :exclusive | :raw | :read | :read_ahead | :sync | :write | {:encoding, :latin1 | :unicode | :utf16 | :utf32 | :utf8 | {:utf16, :big | :little} | {:utf32, :big | :little}} | {:read_ahead, pos_integer} | {:delayed_write, non_neg_integer, non_neg_integer} @doc """ Returns `true` if the path is a regular file. ## Examples File.regular? __ENV__.file #=> true """ @spec regular?(Path.t) :: boolean def regular?(path) do :elixir_utils.read_file_type(IO.chardata_to_string(path)) == {:ok, :regular} end @doc """ Returns `true` if the path is a directory. """ @spec dir?(Path.t) :: boolean def dir?(path) do :elixir_utils.read_file_type(IO.chardata_to_string(path)) == {:ok, :directory} end @doc """ Returns `true` if the given path exists. It can be regular file, directory, socket, symbolic link, named pipe or device file. ## Examples File.exists?("test/") #=> true File.exists?("missing.txt") #=> false File.exists?("/dev/null") #=> true """ @spec exists?(Path.t) :: boolean def exists?(path) do match?({:ok, _}, F.read_file_info(IO.chardata_to_string(path))) end @doc """ Tries to create the directory `path`. Missing parent directories are not created. Returns `:ok` if successful, or `{:error, reason}` if an error occurs. Typical error reasons are: * `:eacces` - missing search or write permissions for the parent directories of `path` * `:eexist` - there is already a file or directory named `path` * `:enoent` - a component of `path` does not exist * `:enospc` - there is a no space left on the device * `:enotdir` - a component of `path` is not a directory; on some platforms, `:enoent` is returned instead """ @spec mkdir(Path.t) :: :ok | {:error, posix} def mkdir(path) do F.make_dir(IO.chardata_to_string(path)) end @doc """ Same as `mkdir/1`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec mkdir!(Path.t) :: :ok | no_return def mkdir!(path) do case mkdir(path) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "make directory", path: IO.chardata_to_string(path) end end @doc """ Tries to create the directory `path`. Missing parent directories are created. Returns `:ok` if successful, or `{:error, reason}` if an error occurs. Typical error reasons are: * `:eacces` - missing search or write permissions for the parent directories of `path` * `:enospc` - there is a no space left on the device * `:enotdir` - a component of `path` is not a directory """ @spec mkdir_p(Path.t) :: :ok | {:error, posix} def mkdir_p(path) do do_mkdir_p(IO.chardata_to_string(path)) end defp do_mkdir_p("/") do :ok end defp do_mkdir_p(path) do if dir?(path) do :ok else parent = Path.dirname(path) if parent == path do # Protect against infinite loop {:error, :einval} else _ = do_mkdir_p(parent) case F.make_dir(path) do {:error, :eexist} = error -> if dir?(path), do: :ok, else: error other -> other end end end end @doc """ Same as `mkdir_p/1`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec mkdir_p!(Path.t) :: :ok | no_return def mkdir_p!(path) do case mkdir_p(path) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "make directory (with -p)", path: IO.chardata_to_string(path) end end @doc """ Returns `{:ok, binary}`, where `binary` is a binary data object that contains the contents of `path`, or `{:error, reason}` if an error occurs. Typical error reasons: * `:enoent` - the file does not exist * `:eacces` - missing permission for reading the file, or for searching one of the parent directories * `:eisdir` - the named file is a directory * `:enotdir` - a component of the file name is not a directory; on some platforms, `:enoent` is returned instead * `:enomem` - there is not enough memory for the contents of the file You can use `:file.format_error/1` to get a descriptive string of the error. """ @spec read(Path.t) :: {:ok, binary} | {:error, posix} def read(path) do F.read_file(IO.chardata_to_string(path)) end @doc """ Returns binary with the contents of the given filename or raises `File.Error` if an error occurs. """ @spec read!(Path.t) :: binary | no_return def read!(path) do case read(path) do {:ok, binary} -> binary {:error, reason} -> raise File.Error, reason: reason, action: "read file", path: IO.chardata_to_string(path) end end @doc """ Returns information about the `path`. If it exists, it returns a `{:ok, info}` tuple, where info is a `File.Stat` struct. Returns `{:error, reason}` with the same reasons as `read/1` if a failure occurs. ## Options The accepted options are: * `:time` - configures how the file timestamps are returned The values for `:time` can be: * `:local` - returns a `{date, time}` tuple using the machine time * `:universal` - returns a `{date, time}` tuple in UTC * `:posix` - returns the time as integer seconds since epoch """ @spec stat(Path.t, stat_options) :: {:ok, File.Stat.t} | {:error, posix} def stat(path, opts \\ []) do case F.read_file_info(IO.chardata_to_string(path), opts) do {:ok, fileinfo} -> {:ok, File.Stat.from_record(fileinfo)} error -> error end end @doc """ Same as `stat/2` but returns the `File.Stat` directly and throws `File.Error` if an error is returned. """ @spec stat!(Path.t, stat_options) :: File.Stat.t | no_return def stat!(path, opts \\ []) do case stat(path, opts) do {:ok, info} -> info {:error, reason} -> raise File.Error, reason: reason, action: "read file stats", path: IO.chardata_to_string(path) end end @doc """ Returns information about the `path`. If the file is a symlink sets the `type` to `:symlink` and returns `File.Stat` for the link. For any other file, returns exactly the same values as `stat/2`. For more details see http://www.erlang.org/doc/man/file.html#read_link_info-2 ## Options The accepted options are: * `:time` - configures how the file timestamps are returned The values for `:time` can be: * `:local` - returns a `{date, time}` tuple using the machine time * `:universal` - returns a `{date, time}` tuple in UTC * `:posix` - returns the time as integer seconds since epoch """ @spec lstat(Path.t, stat_options) :: {:ok, File.Stat.t} | {:error, posix} def lstat(path, opts \\ []) do case F.read_link_info(IO.chardata_to_string(path), opts) do {:ok, fileinfo} -> {:ok, File.Stat.from_record(fileinfo)} error -> error end end @doc """ Same as `lstat/2` but returns the `File.Stat` directly and throws `File.Error` if an error is returned. """ @spec lstat!(Path.t, stat_options) :: File.Stat.t | no_return def lstat!(path, opts \\ []) do case lstat(path, opts) do {:ok, info} -> info {:error, reason} -> raise File.Error, reason: reason, action: "read file stats", path: IO.chardata_to_string(path) end end @doc """ Writes the given `File.Stat` back to the filesystem at the given path. Returns `:ok` or `{:error, reason}`. """ @spec write_stat(Path.t, File.Stat.t, stat_options) :: :ok | {:error, posix} def write_stat(path, stat, opts \\ []) do F.write_file_info(IO.chardata_to_string(path), File.Stat.to_record(stat), opts) end @doc """ Same as `write_stat/3` but raises an exception if it fails. Returns `:ok` otherwise. """ @spec write_stat!(Path.t, File.Stat.t, stat_options) :: :ok | no_return def write_stat!(path, stat, opts \\ []) do case write_stat(path, stat, opts) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "write file stats", path: IO.chardata_to_string(path) end end @doc """ Updates modification time (mtime) and access time (atime) of the given file. File is created if it doesn’t exist. """ @spec touch(Path.t, :calendar.datetime) :: :ok | {:error, posix} def touch(path, time \\ :calendar.local_time) do path = IO.chardata_to_string(path) case F.change_time(path, time) do {:error, :enoent} -> touch_new(path, time) other -> other end end defp touch_new(path, time) do case write(path, "", [:append]) do :ok -> F.change_time(path, time) {:error, _reason} = error -> error end end @doc """ Same as `touch/2` but raises an exception if it fails. Returns `:ok` otherwise. """ @spec touch!(Path.t, :calendar.datetime) :: :ok | no_return def touch!(path, time \\ :calendar.local_time) do case touch(path, time) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "touch", path: IO.chardata_to_string(path) end end @doc """ Creates a symbolic link `new` to the file or directory `existing`. Returns `:ok` if successful, `{:error, reason}` otherwise. If the operating system does not support symlinks, returns `{:error, :enotsup}`. """ def ln_s(existing, new) do F.make_symlink(existing, new) end @doc """ Copies the contents of `source` to `destination`. Both parameters can be a filename or an io device opened with `open/2`. `bytes_count` specifies the number of bytes to copy, the default being `:infinity`. If file `destination` already exists, it is overwritten by the contents in `source`. Returns `{:ok, bytes_copied}` if successful, `{:error, reason}` otherwise. Compared to the `cp/3`, this function is more low-level, allowing a copy from device to device limited by a number of bytes. On the other hand, `cp/3` performs more extensive checks on both source and destination and it also preserves the file mode after copy. Typical error reasons are the same as in `open/2`, `read/1` and `write/3`. """ @spec copy(Path.t, Path.t, pos_integer | :infinity) :: {:ok, non_neg_integer} | {:error, posix} def copy(source, destination, bytes_count \\ :infinity) do F.copy(IO.chardata_to_string(source), IO.chardata_to_string(destination), bytes_count) end @doc """ The same as `copy/3` but raises an `File.CopyError` if it fails. Returns the `bytes_copied` otherwise. """ @spec copy!(Path.t, Path.t, pos_integer | :infinity) :: non_neg_integer | no_return def copy!(source, destination, bytes_count \\ :infinity) do case copy(source, destination, bytes_count) do {:ok, bytes_count} -> bytes_count {:error, reason} -> raise File.CopyError, reason: reason, action: "copy", source: IO.chardata_to_string(source), destination: IO.chardata_to_string(destination) end end @doc """ Copies the contents in `source` to `destination` preserving its mode. If a file already exists in the destination, it invokes a callback which should return `true` if the existing file should be overwritten, `false` otherwise. It defaults to return `true`. It returns `:ok` in case of success, returns `{:error, reason}` otherwise. If you want to copy contents from an io device to another device or do a straight copy from a source to a destination without preserving modes, check `copy/3` instead. Note: The command `cp` in Unix systems behaves differently depending if `destination` is an existing directory or not. We have chosen to explicitly disallow this behaviour. If destination is a directory, an error will be returned. """ @spec cp(Path.t, Path.t, (Path.t, Path.t -> boolean)) :: :ok | {:error, posix} def cp(source, destination, callback \\ fn(_, _) -> true end) do source = IO.chardata_to_string(source) destination = IO.chardata_to_string(destination) case do_cp_file(source, destination, callback, []) do {:error, reason, _} -> {:error, reason} _ -> :ok end end defp path_differs?(path, path), do: false defp path_differs?(p1, p2) do Path.expand(p1) !== Path.expand(p2) end @doc """ The same as `cp/3`, but raises `File.CopyError` if it fails. Returns `:ok` otherwise. """ @spec cp!(Path.t, Path.t, (Path.t, Path.t -> boolean)) :: :ok | no_return def cp!(source, destination, callback \\ fn(_, _) -> true end) do case cp(source, destination, callback) do :ok -> :ok {:error, reason} -> raise File.CopyError, reason: reason, action: "copy", source: IO.chardata_to_string(source), destination: IO.chardata_to_string(destination) end end @doc ~S""" Copies the contents in source to destination. If the source is a file, it copies `source` to `destination`. If the source is a directory, it copies the contents inside source into the destination. If a file already exists in the destination, it invokes a callback which should return `true` if the existing file should be overwritten, `false` otherwise. It defaults to return `true`. If a directory already exists in the destination where a file is meant to be (or otherwise), this function will fail. This function may fail while copying files, in such cases, it will leave the destination directory in a dirty state, where already copied files won't be removed. It returns `{:ok, files_and_directories}` in case of success with all files and directories copied in no specific order, `{:error, reason, file}` otherwise. Note: The command `cp` in Unix systems behaves differently depending if `destination` is an existing directory or not. We have chosen to explicitly disallow this behaviour. ## Examples # Copies "a.txt" to "tmp" File.cp_r "a.txt", "tmp.txt" # Copies all files in "samples" to "tmp" File.cp_r "samples", "tmp" # Same as before, but asks the user how to proceed in case of conflicts File.cp_r "samples", "tmp", fn(source, destination) -> IO.gets("Overwriting #{destination} by #{source}. Type y to confirm.") == "y" end """ @spec cp_r(Path.t, Path.t, (Path.t, Path.t -> boolean)) :: {:ok, [binary]} | {:error, posix, binary} def cp_r(source, destination, callback \\ fn(_, _) -> true end) when is_function(callback) do source = IO.chardata_to_string(source) destination = IO.chardata_to_string(destination) case do_cp_r(source, destination, callback, []) do {:error, _, _} = error -> error res -> {:ok, res} end end @doc """ The same as `cp_r/3`, but raises `File.CopyError` if it fails. Returns the list of copied files otherwise. """ @spec cp_r!(Path.t, Path.t, (Path.t, Path.t -> boolean)) :: [binary] | no_return def cp_r!(source, destination, callback \\ fn(_, _) -> true end) do case cp_r(source, destination, callback) do {:ok, files} -> files {:error, reason, file} -> raise File.CopyError, reason: reason, action: "copy recursively", on: file, source: IO.chardata_to_string(source), destination: IO.chardata_to_string(destination) end end # src may be a file or a directory, dest is definitely # a directory. Returns nil unless an error is found. defp do_cp_r(src, dest, callback, acc) when is_list(acc) do case :elixir_utils.read_link_type(src) do {:ok, :regular} -> do_cp_file(src, dest, callback, acc) {:ok, :symlink} -> case F.read_link(src) do {:ok, link} -> do_cp_link(link, src, dest, callback, acc) {:error, reason} -> {:error, reason, src} end {:ok, :directory} -> case F.list_dir(src) do {:ok, files} -> case mkdir(dest) do success when success in [:ok, {:error, :eexist}] -> Enum.reduce(files, [dest|acc], fn(x, acc) -> do_cp_r(Path.join(src, x), Path.join(dest, x), callback, acc) end) {:error, reason} -> {:error, reason, dest} end {:error, reason} -> {:error, reason, src} end {:ok, _} -> {:error, :eio, src} {:error, reason} -> {:error, reason, src} end end # If we reach this clause, there was an error while # processing a file. defp do_cp_r(_, _, _, acc) do acc end defp copy_file_mode!(src, dest) do write_stat!(dest, %{stat!(dest) | mode: stat!(src).mode}) end # Both src and dest are files. defp do_cp_file(src, dest, callback, acc) do case F.copy(src, {dest, [:exclusive]}) do {:ok, _} -> copy_file_mode!(src, dest) [dest|acc] {:error, :eexist} -> if path_differs?(src, dest) and callback.(src, dest) do case copy(src, dest) do {:ok, _} -> copy_file_mode!(src, dest) [dest|acc] {:error, reason} -> {:error, reason, src} end else acc end {:error, reason} -> {:error, reason, src} end end # Both src and dest are files. defp do_cp_link(link, src, dest, callback, acc) do case F.make_symlink(link, dest) do :ok -> [dest|acc] {:error, :eexist} -> if path_differs?(src, dest) and callback.(src, dest) do # If rm/1 fails, F.make_symlink/2 will fail _ = rm(dest) case F.make_symlink(link, dest) do :ok -> [dest|acc] {:error, reason} -> {:error, reason, src} end else acc end {:error, reason} -> {:error, reason, src} end end @doc """ Writes `content` to the file `path`. The file is created if it does not exist. If it exists, the previous contents are overwritten. Returns `:ok` if successful, or `{:error, reason}` if an error occurs. **Warning:** Every time this function is invoked, a file descriptor is opened and a new process is spawned to write to the file. For this reason, if you are doing multiple writes in a loop, opening the file via `File.open/2` and using the functions in `IO` to write to the file will yield much better performance then calling this function multiple times. Typical error reasons are: * `:enoent` - a component of the file name does not exist * `:enotdir` - a component of the file name is not a directory; on some platforms, enoent is returned instead * `:enospc` - there is a no space left on the device * `:eacces` - missing permission for writing the file or searching one of the parent directories * `:eisdir` - the named file is a directory Check `File.open/2` for other available options. """ @spec write(Path.t, iodata, [mode]) :: :ok | {:error, posix} def write(path, content, modes \\ []) do F.write_file(IO.chardata_to_string(path), content, modes) end @doc """ Same as `write/3` but raises an exception if it fails, returns `:ok` otherwise. """ @spec write!(Path.t, iodata, [mode]) :: :ok | no_return def write!(path, content, modes \\ []) do case F.write_file(path, content, modes) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "write to file", path: IO.chardata_to_string(path) end end @doc """ Tries to delete the file `path`. Returns `:ok` if successful, or `{:error, reason}` if an error occurs. Note the file is deleted even if in read-only mode. Typical error reasons are: * `:enoent` - the file does not exist * `:eacces` - missing permission for the file or one of its parents * `:eperm` - the file is a directory and user is not super-user * `:enotdir` - a component of the file name is not a directory; on some platforms, enoent is returned instead * `:einval` - filename had an improper type, such as tuple ## Examples File.rm("file.txt") #=> :ok File.rm("tmp_dir/") #=> {:error, :eperm} """ @spec rm(Path.t) :: :ok | {:error, posix} def rm(path) do path = IO.chardata_to_string(path) case F.delete(path) do :ok -> :ok {:error, :eacces} = e -> change_mode_windows(path) || e {:error, _} = e -> e end end defp change_mode_windows(path) do if match? {:win32, _}, :os.type do case F.read_file_info(path) do {:ok, file_info} when elem(file_info, 3) in [:read, :none] -> change_mode_windows(path, file_info) _ -> nil end end end defp change_mode_windows(path, file_info) do case chmod(path, (elem(file_info, 7) + 0o200)) do :ok -> F.delete(path) {:error, _reason} = error -> error end end @doc """ Same as `rm/1`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec rm!(Path.t) :: :ok | no_return def rm!(path) do case rm(path) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "remove file", path: IO.chardata_to_string(path) end end @doc """ Tries to delete the dir at `path`. Returns `:ok` if successful, or `{:error, reason}` if an error occurs. ## Examples File.rmdir('tmp_dir') #=> :ok File.rmdir('file.txt') #=> {:error, :enotdir} """ @spec rmdir(Path.t) :: :ok | {:error, posix} def rmdir(path) do F.del_dir(IO.chardata_to_string(path)) end @doc """ Same as `rmdir/1`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec rmdir!(Path.t) :: :ok | {:error, posix} def rmdir!(path) do case rmdir(path) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "remove directory", path: IO.chardata_to_string(path) end end @doc """ Removes files and directories recursively at the given `path`. Symlinks are not followed but simply removed, non-existing files are simply ignored (i.e. doesn't make this function fail). Returns `{:ok, files_and_directories}` with all files and directories removed in no specific order, `{:error, reason, file}` otherwise. ## Examples File.rm_rf "samples" #=> {:ok, ["samples", "samples/1.txt"]} File.rm_rf "unknown" #=> {:ok, []} """ @spec rm_rf(Path.t) :: {:ok, [binary]} | {:error, posix, binary} def rm_rf(path) do do_rm_rf(IO.chardata_to_string(path), {:ok, []}) end defp do_rm_rf(path, {:ok, _} = entry) do case safe_list_dir(path) do {:ok, files} when is_list(files) -> res = Enum.reduce files, entry, fn(file, tuple) -> do_rm_rf(Path.join(path, file), tuple) end case res do {:ok, acc} -> case rmdir(path) do :ok -> {:ok, [path|acc]} {:error, :enoent} -> res {:error, reason} -> {:error, reason, path} end reason -> reason end {:ok, :directory} -> do_rm_directory(path, entry) {:ok, :regular} -> do_rm_regular(path, entry) {:error, reason} when reason in [:enoent, :enotdir] -> entry {:error, reason} -> {:error, reason, path} end end defp do_rm_rf(_, reason) do reason end defp do_rm_regular(path, {:ok, acc} = entry) do case rm(path) do :ok -> {:ok, [path|acc]} {:error, :enoent} -> entry {:error, reason} -> {:error, reason, path} end end # On windows, symlinks are treated as directory and must be removed # with rmdir/1. But on Unix, we remove them via rm/1. So we first try # to remove it as a directory and, if we get :enotdir, we fallback to # a file removal. defp do_rm_directory(path, {:ok, acc} = entry) do case rmdir(path) do :ok -> {:ok, [path|acc]} {:error, :enotdir} -> do_rm_regular(path, entry) {:error, :enoent} -> entry {:error, reason} -> {:error, reason, path} end end defp safe_list_dir(path) do case :elixir_utils.read_link_type(path) do {:ok, :symlink} -> case :elixir_utils.read_file_type(path) do {:ok, :directory} -> {:ok, :directory} _ -> {:ok, :regular} end {:ok, :directory} -> F.list_dir(path) {:ok, _} -> {:ok, :regular} {:error, reason} -> {:error, reason} end end @doc """ Same as `rm_rf/1` but raises `File.Error` in case of failures, otherwise the list of files or directories removed. """ @spec rm_rf!(Path.t) :: [binary] | no_return def rm_rf!(path) do case rm_rf(path) do {:ok, files} -> files {:error, reason, _} -> raise File.Error, reason: reason, path: IO.chardata_to_string(path), action: "remove files and directories recursively from" end end @doc ~S""" Opens the given `path` according to the given list of modes. In order to write and read files, one must use the functions in the `IO` module. By default, a file is opened in binary mode which requires the functions `IO.binread/2` and `IO.binwrite/2` to interact with the file. A developer may pass `:utf8` as an option when opening the file and then all other functions from `IO` are available, since they work directly with Unicode data. The allowed modes: * `:read` - the file, which must exist, is opened for reading. * `:write` - the file is opened for writing. It is created if it does not exist. If the file does exists, and if write is not combined with read, the file will be truncated. * `:append` - the file will be opened for writing, and it will be created if it does not exist. Every write operation to a file opened with append will take place at the end of the file. * `:exclusive` - the file, when opened for writing, is created if it does not exist. If the file exists, open will return `{:error, :eexist}`. * `:char_list` - when this term is given, read operations on the file will return char lists rather than binaries. * `:compressed` - makes it possible to read or write gzip compressed files. The compressed option must be combined with either read or write, but not both. Note that the file size obtained with `stat/1` will most probably not match the number of bytes that can be read from a compressed file. * `:utf8` - this option denotes how data is actually stored in the disk file and makes the file perform automatic translation of characters to and from utf-8. If data is sent to a file in a format that cannot be converted to the utf-8 or if data is read by a function that returns data in a format that cannot cope with the character range of the data, an error occurs and the file will be closed. Check http://www.erlang.org/doc/man/file.html#open-2 for more information about other options like `:read_ahead` and `:delayed_write`. This function returns: * `{:ok, io_device}` - the file has been opened in the requested mode. `io_device` is actually the pid of the process which handles the file. This process is linked to the process which originally opened the file. If any process to which the `io_device` is linked terminates, the file will be closed and the process itself will be terminated. An `io_device` returned from this call can be used as an argument to the `IO` module functions. * `{:error, reason}` - the file could not be opened. ## Examples {:ok, file} = File.open("foo.tar.gz", [:read, :compressed]) IO.read(file, :line) File.close(file) """ @spec open(Path.t, [mode | :ram]) :: {:ok, io_device} | {:error, posix} @spec open(Path.t, (io_device -> res)) :: {:ok, res} | {:error, posix} when res: var def open(path, modes \\ []) def open(path, modes) when is_list(modes) do F.open(IO.chardata_to_string(path), open_defaults(modes, true)) end def open(path, function) when is_function(function) do open(path, [], function) end @doc """ Similar to `open/2` but expects a function as last argument. The file is opened, given to the function as argument and automatically closed after the function returns, regardless if there was an error when executing the function. It returns `{:ok, function_result}` in case of success, `{:error, reason}` otherwise. This function expects the file to be closed with success, which is usually the case unless the `:delayed_write` option is given. For this reason, we do not recommend passing `:delayed_write` to this function. ## Examples File.open("file.txt", [:read, :write], fn(file) -> IO.read(file, :line) end) """ @spec open(Path.t, [mode | :ram], (io_device -> res)) :: {:ok, res} | {:error, posix} when res: var def open(path, modes, function) do case open(path, modes) do {:ok, device} -> try do {:ok, function.(device)} after :ok = close(device) end other -> other end end @doc """ Same as `open/2` but raises an error if file could not be opened. Returns the `io_device` otherwise. """ @spec open!(Path.t, [mode]) :: io_device | no_return def open!(path, modes \\ []) do case open(path, modes) do {:ok, device} -> device {:error, reason} -> raise File.Error, reason: reason, action: "open", path: IO.chardata_to_string(path) end end @doc """ Same as `open/3` but raises an error if file could not be opened. Returns the function result otherwise. """ @spec open!(Path.t, [mode | :ram], (io_device -> res)) :: res | no_return when res: var def open!(path, modes, function) do case open(path, modes, function) do {:ok, device} -> device {:error, reason} -> raise File.Error, reason: reason, action: "open", path: IO.chardata_to_string(path) end end @doc """ Gets the current working directory. In rare circumstances, this function can fail on Unix. It may happen if read permission does not exist for the parent directories of the current directory. For this reason, returns `{:ok, cwd}` in case of success, `{:error, reason}` otherwise. """ @spec cwd() :: {:ok, binary} | {:error, posix} def cwd() do case F.get_cwd do {:ok, base} -> {:ok, IO.chardata_to_string(fix_drive_letter(base))} {:error, _} = error -> error end end defp fix_drive_letter([l, ?:, ?/ | rest] = original) when l in ?A..?Z do case :os.type() do {:win32, _} -> [l+?a-?A, ?:, ?/ | rest] _ -> original end end defp fix_drive_letter(original), do: original @doc """ The same as `cwd/0`, but raises an exception if it fails. """ @spec cwd!() :: binary | no_return def cwd!() do case cwd() do {:ok, cwd} -> cwd {:error, reason} -> raise File.Error, reason: reason, action: "get current working directory" end end @doc """ Sets the current working directory. Returns `:ok` if successful, `{:error, reason}` otherwise. """ @spec cd(Path.t) :: :ok | {:error, posix} def cd(path) do F.set_cwd(IO.chardata_to_string(path)) end @doc """ The same as `cd/1`, but raises an exception if it fails. """ @spec cd!(Path.t) :: :ok | no_return def cd!(path) do case cd(path) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "set current working directory to", path: IO.chardata_to_string(path) end end @doc """ Changes the current directory to the given `path`, executes the given function and then revert back to the previous path regardless if there is an exception. Raises an error if retrieving or changing the current directory fails. """ @spec cd!(Path.t, (() -> res)) :: res | no_return when res: var def cd!(path, function) do old = cwd! cd!(path) try do function.() after cd!(old) end end @doc """ Returns list of files in the given directory. It returns `{:ok, [files]}` in case of success, `{:error, reason}` otherwise. """ @spec ls(Path.t) :: {:ok, [binary]} | {:error, posix} def ls(path \\ ".") do case F.list_dir(IO.chardata_to_string(path)) do {:ok, file_list} -> {:ok, Enum.map(file_list, &IO.chardata_to_string/1)} {:error, _} = error -> error end end @doc """ The same as `ls/1` but raises `File.Error` in case of an error. """ @spec ls!(Path.t) :: [binary] | no_return def ls!(path \\ ".") do case ls(path) do {:ok, value} -> value {:error, reason} -> raise File.Error, reason: reason, action: "list directory", path: IO.chardata_to_string(path) end end @doc """ Closes the file referenced by `io_device`. It mostly returns `:ok`, except for some severe errors such as out of memory. Note that if the option `:delayed_write` was used when opening the file, `close/1` might return an old write error and not even try to close the file. See `open/2`. """ @spec close(io_device) :: :ok | {:error, posix | :badarg | :terminated} def close(io_device) do F.close(io_device) end @doc """ Returns a `File.Stream` for the given `path` with the given `modes`. The stream implements both `Enumerable` and `Collectable` protocols, which means it can be used both for read and write. The `line_or_byte` argument configures how the file is read when streaming, by `:line` (default) or by a given number of bytes. Operating the stream can fail on open for the same reasons as `File.open!/2`. Note that the file is automatically opened only and every time streaming begins. There is no need to pass `:read` and `:write` modes, as those are automatically set by Elixir. ## Raw files Since Elixir controls when the streamed file is opened, the underlying device cannot be shared and as such it is convenient to open the file in raw mode for performance reasons. Therefore, Elixir **will** open streams in `:raw` mode with the `:read_ahead` option unless an encoding is specified. One may also consider passing the `:delayed_write` option if the stream is meant to be written to under a tight loop. """ def stream!(path, modes \\ [], line_or_bytes \\ :line) do modes = open_defaults(modes, true) File.Stream.__build__(IO.chardata_to_string(path), modes, line_or_bytes) end @doc """ Changes the `mode` for a given `file`. Returns `:ok` on success, or `{:error, reason}` on failure. ## Permissions * 0o400 - read permission: owner * 0o200 - write permission: owner * 0o100 - execute permission: owner * 0o040 - read permission: group * 0o020 - write permission: group * 0o010 - execute permission: group * 0o004 - read permission: other * 0o002 - write permission: other * 0o001 - execute permission: other For example, setting the mode 0o755 gives it write, read and execute permission to the owner and both read and execute permission to group and others. """ @spec chmod(Path.t, non_neg_integer) :: :ok | {:error, posix} def chmod(path, mode) do F.change_mode(IO.chardata_to_string(path), mode) end @doc """ Same as `chmod/2`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec chmod!(Path.t, non_neg_integer) :: :ok | no_return def chmod!(path, mode) do case chmod(path, mode) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "change mode for", path: IO.chardata_to_string(path) end end @doc """ Changes the user group given by the group id `gid` for a given `file`. Returns `:ok` on success, or `{:error, reason}` on failure. """ @spec chgrp(Path.t, non_neg_integer) :: :ok | {:error, posix} def chgrp(path, gid) do F.change_group(IO.chardata_to_string(path), gid) end @doc """ Same as `chgrp/2`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec chgrp!(Path.t, non_neg_integer) :: :ok | no_return def chgrp!(path, gid) do case chgrp(path, gid) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "change group for", path: IO.chardata_to_string(path) end end @doc """ Changes the owner given by the user id `uid` for a given `file`. Returns `:ok` on success, or `{:error, reason}` on failure. """ @spec chown(Path.t, non_neg_integer) :: :ok | {:error, posix} def chown(path, uid) do F.change_owner(IO.chardata_to_string(path), uid) end @doc """ Same as `chown/2`, but raises an exception in case of failure. Otherwise `:ok`. """ @spec chown!(Path.t, non_neg_integer) :: :ok | no_return def chown!(path, uid) do case chown(path, uid) do :ok -> :ok {:error, reason} -> raise File.Error, reason: reason, action: "change owner for", path: IO.chardata_to_string(path) end end ## Helpers @read_ahead 64*1024 defp open_defaults([:char_list|t], _add_binary) do open_defaults(t, false) end defp open_defaults([:utf8|t], add_binary) do open_defaults([{:encoding, :utf8}|t], add_binary) end defp open_defaults([:read_ahead|t], add_binary) do open_defaults([{:read_ahead, @read_ahead}|t], add_binary) end defp open_defaults([h|t], add_binary) do [h|open_defaults(t, add_binary)] end defp open_defaults([], true), do: [:binary] defp open_defaults([], false), do: [] end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/file/000077500000000000000000000000001254730255300206445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/file/stat.ex000066400000000000000000000045311254730255300221600ustar00rootroot00000000000000require Record defmodule File.Stat do @moduledoc """ A struct responsible to hold file information. In Erlang, this struct is represented by a `:file_info` record. Therefore this module also provides functions for converting between the Erlang record and the Elixir struct. Its fields are: * `size` - size of file in bytes. * `type` - `:device | :directory | :regular | :other`; the type of the file. * `access` - `:read | :write | :read_write | :none`; the current system access to the file. * `atime` - the last time the file was read. * `mtime` - the last time the file was written. * `ctime` - the interpretation of this time field depends on the operating system. On Unix, it is the last time the file or the inode was changed. In Windows, it is the time of creation. * `mode` - the file permissions. * `links` - the number of links to this file. This is always 1 for file systems which have no concept of links. * `major_device` - identifies the file system where the file is located. In windows, the number indicates a drive as follows: 0 means A:, 1 means B:, and so on. * `minor_device` - only valid for character devices on Unix. In all other cases, this field is zero. * `inode` - gives the inode number. On non-Unix file systems, this field will be zero. * `uid` - indicates the owner of the file. * `gid` - gives the group that the owner of the file belongs to. Will be zero for non-Unix file systems. The time type returned in `atime`, `mtime`, and `ctime` is dependent on the time type set in options. `{:time, type}` where type can be `:local`, `:universal`, or `:posix`. Default is `:local`. """ record = Record.extract(:file_info, from_lib: "kernel/include/file.hrl") keys = :lists.map(&elem(&1, 0), record) vals = :lists.map(&{&1, [], nil}, keys) pairs = :lists.zip(keys, vals) defstruct keys @type t :: %__MODULE__{} @doc """ Converts a `File.Stat` struct to a `:file_info` record. """ def to_record(%File.Stat{unquote_splicing(pairs)}) do {:file_info, unquote_splicing(vals)} end @doc """ Converts a `:file_info` record into a `File.Stat`. """ def from_record(file_info) def from_record({:file_info, unquote_splicing(vals)}) do %File.Stat{unquote_splicing(pairs)} end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/file/stream.ex000066400000000000000000000052621254730255300225020ustar00rootroot00000000000000defmodule File.Stream do @moduledoc """ Defines a `File.Stream` struct returned by `File.stream!/3`. The following fields are public: * `path` - the file path * `modes` - the file modes * `raw` - a boolean indicating if bin functions should be used * `line_or_bytes` - if reading should read lines or a given amount of bytes """ defstruct path: nil, modes: [], line_or_bytes: :line, raw: true @type t :: %__MODULE__{} @doc false def __build__(path, modes, line_or_bytes) do raw = :lists.keyfind(:encoding, 1, modes) == false modes = if raw do if :lists.keyfind(:read_ahead, 1, modes) == {:read_ahead, false} do [:raw|modes] else [:raw, :read_ahead|modes] end else modes end %File.Stream{path: path, modes: modes, raw: raw, line_or_bytes: line_or_bytes} end defimpl Collectable do def into(%{path: path, modes: modes, raw: raw} = stream) do modes = for mode <- modes, not mode in [:read], do: mode case :file.open(path, [:write|modes]) do {:ok, device} -> {:ok, into(device, stream, raw)} {:error, reason} -> raise File.Error, reason: reason, action: "stream", path: path end end defp into(device, stream, raw) do fn :ok, {:cont, x} -> case raw do true -> IO.binwrite(device, x) false -> IO.write(device, x) end :ok, :done -> # If delayed_write option is used and the last write failed will # MatchError here as {:error, _} is returned. :ok = :file.close(device) stream :ok, :halt -> # If delayed_write option is used and the last write failed will # MatchError here as {:error, _} is returned. :ok = :file.close(device) end end end defimpl Enumerable do def reduce(%{path: path, modes: modes, line_or_bytes: line_or_bytes, raw: raw}, acc, fun) do modes = for mode <- modes, not mode in [:write, :append], do: mode start_fun = fn -> case :file.open(path, modes) do {:ok, device} -> device {:error, reason} -> raise File.Error, reason: reason, action: "stream", path: path end end next_fun = case raw do true -> &IO.each_binstream(&1, line_or_bytes) false -> &IO.each_stream(&1, line_or_bytes) end Stream.resource(start_fun, next_fun, &:file.close/1).(acc, fun) end def count(_stream) do {:error, __MODULE__} end def member?(_stream, _term) do {:error, __MODULE__} end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/float.ex000066400000000000000000000146071254730255300214000ustar00rootroot00000000000000import Kernel, except: [round: 1] defmodule Float do @moduledoc """ Functions for working with floating point numbers. """ @doc """ Parses a binary into a float. If successful, returns a tuple of the form `{float, remainder_of_binary}`; otherwise, `:error`. If a float formatted string wants to be directly converted to a float, `String.to_float/1" can be used instead. ## Examples iex> Float.parse("34") {34.0, ""} iex> Float.parse("34.25") {34.25, ""} iex> Float.parse("56.5xyz") {56.5, "xyz"} iex> Float.parse("pi") :error """ @spec parse(binary) :: {float, binary} | :error def parse("-" <> binary) do case parse_unsigned(binary) do :error -> :error {number, remainder} -> {-number, remainder} end end def parse(binary) do parse_unsigned(binary) end defp parse_unsigned(<>) when char in ?0..?9, do: parse_unsigned(rest, false, false, <>) defp parse_unsigned(binary) when is_binary(binary), do: :error defp parse_unsigned(<>, dot?, e?, acc) when char in ?0..?9, do: parse_unsigned(rest, dot?, e?, <>) defp parse_unsigned(<>, false, false, acc) when char in ?0..?9, do: parse_unsigned(rest, true, false, <>) defp parse_unsigned(<>, dot?, false, acc) when char in ?0..?9, do: parse_unsigned(rest, true, true, <>) defp parse_unsigned(<>, dot?, false, acc) when char in ?0..?9, do: parse_unsigned(rest, true, true, <>) defp parse_unsigned(rest, dot?, _e?, acc), do: {:erlang.binary_to_float(add_dot(acc, dot?)), rest} defp add_dot(acc, true), do: acc defp add_dot(acc, false), do: acc <> ".0" @doc """ Rounds a float to the largest integer less than or equal to `num`. `floor/2` also accepts a precision to round a floating point value down to an arbitrary number of fractional digits (between 0 and 15). This function always returns a float. `Kernel.trunc/1` may be used instead to truncate the result to an integer afterwards. ## Examples iex> Float.floor(34.25) 34.0 iex> Float.floor(-56.5) -57.0 iex> Float.floor(34.253, 2) 34.25 """ @spec floor(float, 0..15) :: float def floor(number, precision \\ 0) when is_float(number) and precision in 0..15 do power = power_of_10(precision) number = number * power truncated = trunc(number) variance = if number - truncated < 0, do: -1.0, else: 0.0 (truncated + variance) / power end @doc """ Rounds a float to the largest integer greater than or equal to `num`. `ceil/2` also accepts a precision to round a floating point value down to an arbitrary number of fractional digits (between 0 and 15). This function always returns floats. `Kernel.trunc/1` may be used instead to truncate the result to an integer afterwards. ## Examples iex> Float.ceil(34.25) 35.0 iex> Float.ceil(-56.5) -56.0 iex> Float.ceil(34.253, 2) 34.26 """ @spec ceil(float, 0..15) :: float def ceil(number, precision \\ 0) when is_float(number) and precision in 0..15 do power = power_of_10(precision) number = number * power truncated = trunc(number) variance = if number - truncated > 0, do: 1.0, else: 0.0 (truncated + variance) / power end @doc """ Rounds a floating point value to an arbitrary number of fractional digits (between 0 and 15). This function only accepts floats and always returns a float. Use `Kernel.round/1` if you want a function that accepts both floats and integers and always returns an integer. ## Examples iex> Float.round(5.5674, 3) 5.567 iex> Float.round(5.5675, 3) 5.568 iex> Float.round(-5.5674, 3) -5.567 iex> Float.round(-5.5675, 3) -5.568 """ @spec round(float, 0..15) :: float def round(number, precision \\ 0) when is_float(number) and precision in 0..15 do power = power_of_10(precision) Kernel.round(number * power) / power end Enum.reduce 0..15, 1, fn x, acc -> defp power_of_10(unquote(x)), do: unquote(acc) acc * 10 end @doc """ Returns a char list which corresponds to the text representation of the given float. Inlined by the compiler. ## Examples iex> Float.to_char_list(7.0) '7.00000000000000000000e+00' """ @spec to_char_list(float) :: char_list def to_char_list(float) do :erlang.float_to_list(float) end @doc """ Returns a list which corresponds to the text representation of the given float. ## Options * `:decimals` — number of decimal points to show * `:scientific` — number of decimal points to show, in scientific format * `:compact` — when `true`, use the most compact representation (ignored with the `scientific` option) ## Examples iex> Float.to_char_list 7.1, [decimals: 2, compact: true] '7.1' """ @spec to_char_list(float, list) :: char_list def to_char_list(float, options) do :erlang.float_to_list(float, expand_compact(options)) end @doc """ Returns a binary which corresponds to the text representation of the given float. Inlined by the compiler. ## Examples iex> Float.to_string(7.0) "7.00000000000000000000e+00" """ @spec to_string(float) :: String.t def to_string(float) do :erlang.float_to_binary(float) end @doc """ Returns a binary which corresponds to the text representation of `float`. ## Options * `:decimals` — number of decimal points to show * `:scientific` — number of decimal points to show, in scientific format * `:compact` — when `true`, use the most compact representation (ignored with the `scientific` option) ## Examples iex> Float.to_string 7.1, [decimals: 2, compact: true] "7.1" """ @spec to_string(float, list) :: String.t def to_string(float, options) do :erlang.float_to_binary(float, expand_compact(options)) end defp expand_compact([{:compact, false}|t]), do: expand_compact(t) defp expand_compact([{:compact, true}|t]), do: [:compact|expand_compact(t)] defp expand_compact([h|t]), do: [h|expand_compact(t)] defp expand_compact([]), do: [] end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/gen_event.ex000066400000000000000000001043241254730255300222410ustar00rootroot00000000000000defmodule GenEvent do @moduledoc """ A behaviour module for implementing event handling functionality. The event handling model consists of a generic event manager process with an arbitrary number of event handlers which are added and deleted dynamically. An event manager implemented using this module will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree. ## Example There are many use cases for event handlers. For example, a logging system can be built using event handlers where each log message is an event and different event handlers can be plugged to handle the log messages. One handler may print error messages on the terminal, another can write it to a file, while a third one can keep the messages in memory (like a buffer) until they are read. As an example, let's have a GenEvent that accumulates messages until they are collected by an explicit call. defmodule LoggerHandler do use GenEvent # Callbacks def handle_event({:log, x}, messages) do {:ok, [x|messages]} end def handle_call(:messages, messages) do {:ok, Enum.reverse(messages), []} end end {:ok, pid} = GenEvent.start_link() GenEvent.add_handler(pid, LoggerHandler, []) #=> :ok GenEvent.notify(pid, {:log, 1}) #=> :ok GenEvent.notify(pid, {:log, 2}) #=> :ok GenEvent.call(pid, LoggerHandler, :messages) #=> [1, 2] GenEvent.call(pid, LoggerHandler, :messages) #=> [] We start a new event manager by calling `GenEvent.start_link/0`. Notifications can be sent to the event manager which will then invoke `handle_event/2` for each registered handler. We can add new handlers with `add_handler/3` and `add_mon_handler/3`. Calls can also be made to specific handlers by using `call/3`. ## Callbacks There are 6 callbacks required to be implemented in a `GenEvent`. By adding `use GenEvent` to your module, Elixir will automatically define all 6 callbacks for you, leaving it up to you to implement the ones you want to customize. The callbacks are: * `init(args)` - invoked when the event handler is added. It must return: - `{:ok, state}` - `{:ok, state, :hibernate}` - `{:error, reason}` * `handle_event(msg, state)` - invoked whenever an event is sent via `notify/2`, `ack_notify/2` or `sync_notify/2`. It must return: - `{:ok, new_state}` - `{:ok, new_state, :hibernate}` - `:remove_handler` * `handle_call(msg, state)` - invoked when a `call/3` is done to a specific handler. It must return: - `{:ok, reply, new_state}` - `{:ok, reply, new_state, :hibernate}` - `{:remove_handler, reply}` * `handle_info(msg, state)` - invoked to handle all other messages which are received by the process. Must return the same values as `handle_event/2`. * `terminate(reason, state)` - called when the event handler is removed or the event manager is terminating. It can return any term. The reason is one of: - `:stop` - manager is terminating - `{:stop, reason}` - monitored process terminated (for monitored handlers) - `:remove_handler` - handler is being removed - `{:error, term}` - handler crashed or returned a bad value - `term` - any term passed to functions like `GenEvent.remove_handler/2` * `code_change(old_vsn, state, extra)` - called when the application code is being upgraded live (hot code swapping). It must return: - `{:ok, new_state}` ## Name Registration A GenEvent is bound to the same name registration rules as a `GenServer`. Read more about it in the `GenServer` docs. ## Modes GenEvent stream supports three different notifications. On `GenEvent.ack_notify/2`, the manager acknowledges each event, providing backpressure, but processing of the message happens asynchronously. On `GenEvent.sync_notify/2`, the manager acknowledges an event just after it was processed by all event handlers. On `GenEvent.notify/2`, all events are processed asynchronously and there is no ack (which means there is no backpressure). ## Streaming `GenEvent` messages can be streamed with the help of `stream/2`. You will need to start another process to consume the stream: Task.start_link fn -> stream = GenEvent.stream(pid) # Discard the next 3 events _ = Enum.drop(stream, 3) # Print all remaining events for event <- stream do IO.inspect event end end Now call `GenEvent.notify/2` multiple times. You will see the first three events will be skipped while the rest will be continuously printed. ## Learn more and compatibility If you wish to find out more about gen events, Elixir getting started guides provide a tutorial-like introduction. The documentation and links in Erlang can also provide extra insight. * http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html * http://www.erlang.org/doc/man/gen_event.html * http://learnyousomeerlang.com/event-handlers Keep in mind though Elixir and Erlang gen events are not 100% compatible. The `:gen_event.add_sup_handler/3` is not supported by Elixir's GenEvent, which in turn supports `GenEvent.add_mon_handler/3`. The benefits of the monitoring approach are described in the "Don't drink too much kool aid" section of the "Learn you some Erlang" link above. Due to those changes, Elixir's GenEvent does not trap exits by default. Furthermore, Elixir's also normalizes the `{:error, _}` tuples returned by many functions, in order to be more consistent with themselves and the `GenServer` module. """ @typedoc "Return values of `start*` functions" @type on_start :: {:ok, pid} | {:error, {:already_started, pid}} @typedoc "The GenEvent manager name" @type name :: atom | {:global, term} | {:via, module, term} @typedoc "Options used by the `start*` functions" @type options :: [name: name] @typedoc "The event manager reference" @type manager :: pid | name | {atom, node} @typedoc "Supported values for new handlers" @type handler :: atom | {atom, term} | {pid, reference} @doc false defmacro __using__(_) do quote location: :keep do @behaviour :gen_event @doc false def init(args) do {:ok, args} end @doc false def handle_event(_event, state) do {:ok, state} end @doc false def handle_call(msg, state) do # We do this to trick dialyzer to not complain about non-local returns. case :random.uniform(1) do 1 -> exit({:bad_call, msg}) 2 -> {:remove_handler, :ok} end end @doc false def handle_info(_msg, state) do {:ok, state} end @doc false def terminate(_reason, _state) do :ok end @doc false def code_change(_old, state, _extra) do {:ok, state} end defoverridable [init: 1, handle_event: 2, handle_call: 2, handle_info: 2, terminate: 2, code_change: 3] end end @doc """ Starts an event manager linked to the current process. This is often used to start the `GenEvent` as part of a supervision tree. It accepts the `:name` option which is described under the `Name Registration` section in the `GenServer` module docs. If the event manager is successfully created and initialized, the function returns `{:ok, pid}`, where pid is the pid of the server. If a process with the specified server name already exists, the function returns `{:error, {:already_started, pid}}` with the pid of that process. Note that a `GenEvent` started with `start_link/1` is linked to the parent process and will exit not only on crashes but also if the parent process exits with `:normal` reason. """ @spec start_link(options) :: on_start def start_link(options \\ []) when is_list(options) do do_start(:link, options) end @doc """ Starts an event manager process without links (outside of a supervision tree). See `start_link/1` for more information. """ @spec start(options) :: on_start def start(options \\ []) when is_list(options) do do_start(:nolink, options) end @no_callback :"no callback module" defp do_start(mode, options) do case Keyword.get(options, :name) do nil -> :gen.start(GenEvent, mode, @no_callback, [], []) atom when is_atom(atom) -> :gen.start(GenEvent, mode, {:local, atom}, @no_callback, [], []) other when is_tuple(other) -> :gen.start(GenEvent, mode, other, @no_callback, [], []) end end @doc """ Returns a stream that consumes events from the `manager`. The stream is a `GenEvent` struct that implements the `Enumerable` protocol. Consumption of events only begins when enumeration starts. Note streaming is specific to Elixir's GenEvent and does not work with Erlang ones. ## Options * `:timeout` - raises if no event arrives in X milliseconds (defaults to `:infinity`) """ @spec stream(manager, Keyword.t) :: GenEvent.Stream.t def stream(manager, options \\ []) do %GenEvent.Stream{ manager: manager, timeout: Keyword.get(options, :timeout, :infinity)} end @doc """ Adds a new event handler to the event `manager`. The event manager will call the `init/1` callback with `args` to initiate the event handler and its internal state. If `init/1` returns a correct value indicating successful completion, the event manager adds the event handler and this function returns `:ok`. If the callback fails with `reason` or returns `{:error, reason}`, the event handler is ignored and this function returns `{:error, reason}`. If the given handler was previously installed at the manager, this function returns `{:error, :already_present}`. """ @spec add_handler(manager, handler, term) :: :ok | {:error, term} def add_handler(manager, handler, args) do rpc(manager, {:add_handler, handler, args}) end @doc """ Adds a monitored event handler to the event `manager`. Expects the same input and returns the same values as `add_handler/3`. ## Monitored handlers A monitored handler implies the calling process will now be monitored by the GenEvent manager. If the calling process later terminates with `reason`, the event manager will delete the event handler by calling the `terminate/2` callback with `{:stop, reason}` as argument. If the event handler later is deleted, the event manager sends a message `{:gen_event_EXIT, handler, reason}` to the calling process. Reason is one of the following: * `:normal` - if the event handler has been removed due to a call to `remove_handler/3`, or `:remove_handler` has been returned by a callback function * `:shutdown` - if the event handler has been removed because the event manager is terminating * `{:swapped, new_handler, pid}` - if the process pid has replaced the event handler by another * a term - if the event handler is removed due to an error. Which term depends on the error Keep in mind that the `{:gen_event_EXIT, handler, reason}` message is not guaranteed to be delivered in case the manager crashes. If you want to guarantee the message is delivered, you have two options: * monitor the event manager * link to the event manager and then set `Process.flag(:trap_exit, true)` in your handler callback Finally, this functionality only works with GenEvent started via this module (it is not backwards compatible with Erlang's `:gen_event`). """ @spec add_mon_handler(manager, handler, term) :: :ok | {:error, term} def add_mon_handler(manager, handler, args) do rpc(manager, {:add_mon_handler, handler, args, self()}) end @doc """ Sends an event notification to the event `manager`. The event manager will call `handle_event/2` for each installed event handler. `notify` is asynchronous and will return immediately after the notification is sent. `notify` will not fail even if the specified event manager does not exist, unless it is specified as an atom. """ @spec notify(manager, term) :: :ok def notify(manager, event) def notify({:global, name}, msg) do try do :global.send(name, {:notify, msg}) :ok catch _, _ -> :ok end end def notify({:via, mod, name}, msg) do try do mod.send(name, {:notify, msg}) :ok catch _, _ -> :ok end end def notify(other, msg) do send(other, {:notify, msg}) :ok end @doc """ Sends a sync event notification to the event `manager`. In other words, this function only returns `:ok` after the event manager invokes the `handle_event/2` callback on each installed event handler. See `notify/2` for more info. """ @spec sync_notify(manager, term) :: :ok def sync_notify(manager, event) do rpc(manager, {:sync_notify, event}) end @doc """ Sends a ack event notification to the event `manager`. In other words, this function only returns `:ok` as soon as the event manager starts processing this event, but it does not wait for event handlers to process the sent event. See `notify/2` for more info. Note this function is specific to Elixir's GenEvent and does not work with Erlang ones. """ @spec ack_notify(manager, term) :: :ok def ack_notify(manager, event) do rpc(manager, {:ack_notify, event}) end @doc """ Makes a synchronous call to the event `handler` installed in `manager`. The given `request` is sent and the caller waits until a reply arrives or a timeout occurs. The event manager will call `handle_call/2` to handle the request. The return value `reply` is defined in the return value of `handle_call/2`. If the specified event handler is not installed, the function returns `{:error, :not_found}`. """ @spec call(manager, handler, term, timeout) :: term | {:error, term} def call(manager, handler, request, timeout \\ 5000) do try do :gen.call(manager, self(), {:call, handler, request}, timeout) catch :exit, reason -> exit({reason, {__MODULE__, :call, [manager, handler, request, timeout]}}) else {:ok, res} -> res end end @doc """ Removes an event handler from the event `manager`. The event manager will call `terminate/2` to terminate the event handler and return the callback value. If the specified event handler is not installed, the function returns `{:error, :not_found}`. """ @spec remove_handler(manager, handler, term) :: term | {:error, term} def remove_handler(manager, handler, args) do rpc(manager, {:delete_handler, handler, args}) end @doc """ Replaces an old event handler with a new one in the event `manager`. First, the old event handler is deleted by calling `terminate/2` with the given `args1` and collects the return value. Then the new event handler is added and initiated by calling `init({args2, term})`, where `term` is the return value of calling `terminate/2` in the old handler. This makes it possible to transfer information from one handler to another. The new handler will be added even if the specified old event handler is not installed or if the handler fails to terminate with a given reason in which case `state = {:error, term}`. If `init/1` in the second handler returns a correct value, this function returns `:ok`. """ @spec swap_handler(manager, handler, term, handler, term) :: :ok | {:error, term} def swap_handler(manager, handler1, args1, handler2, args2) do rpc(manager, {:swap_handler, handler1, args1, handler2, args2}) end @doc """ Replaces an old event handler with a new monitored one in the event `manager`. Read the docs for `add_mon_handler/3` and `swap_handler/5` for more information. """ @spec swap_mon_handler(manager, handler, term, handler, term) :: :ok | {:error, term} def swap_mon_handler(manager, handler1, args1, handler2, args2) do rpc(manager, {:swap_mon_handler, handler1, args1, handler2, args2, self()}) end @doc """ Returns a list of all event handlers installed in the `manager`. """ @spec which_handlers(manager) :: [handler] def which_handlers(manager) do rpc(manager, :which_handlers) end @doc """ Terminates the event `manager`. Before terminating, the event manager will call `terminate(:stop, ...)` for each installed event handler. """ @spec stop(manager) :: :ok def stop(manager) do rpc(manager, :stop) end defp rpc(module, cmd) do # TODO: Change the tag on OTP 18 {:ok, reply} = :gen.call(module, self(), cmd, :infinity) reply end ## Init callbacks require Record Record.defrecordp :handler, [:module, :id, :state, :pid, :ref] @doc false def init_it(starter, :self, name, mod, args, options) do init_it(starter, self(), name, mod, args, options) end def init_it(starter, parent, name, _, _, options) do Process.put(:"$initial_call", {__MODULE__, :init_it, 6}) debug = :gen.debug_options(options) :proc_lib.init_ack(starter, {:ok, self()}) loop(parent, name(name), [], debug, false) end @doc false def init_hib(parent, name, handlers, debug) do fetch_msg(parent, name, handlers, debug, true) end defp name({:local, name}), do: name defp name({:global, name}), do: name defp name({:via, _, name}), do: name defp name(pid) when is_pid(pid), do: pid ## Loop defp loop(parent, name, handlers, debug, true) do :proc_lib.hibernate(__MODULE__, :init_hib, [parent, name, handlers, debug]) end defp loop(parent, name, handlers, debug, false) do fetch_msg(parent, name, handlers, debug, false) end defp fetch_msg(parent, name, handlers, debug, hib) do receive do {:system, from, req} -> :sys.handle_system_msg(req, from, parent, __MODULE__, debug, [name, handlers, hib], hib) {:EXIT, ^parent, reason} -> server_terminate(reason, parent, handlers, name) msg when debug == [] -> handle_msg(msg, parent, name, handlers, []) msg -> debug = :sys.handle_debug(debug, &print_event/3, name, {:in, msg}) handle_msg(msg, parent, name, handlers, debug) end end defp handle_msg(msg, parent, name, handlers, debug) do case msg do {:notify, event} -> {hib, handlers} = server_event(:async, event, handlers, name) loop(parent, name, handlers, debug, hib) {_from, _tag, {:notify, event}} -> {hib, handlers} = server_event(:async, event, handlers, name) loop(parent, name, handlers, debug, hib) {_from, tag, {:ack_notify, event}} -> reply(tag, :ok) {hib, handlers} = server_event(:ack, event, handlers, name) loop(parent, name, handlers, debug, hib) {_from, tag, {:sync_notify, event}} -> {hib, handlers} = server_event(:sync, event, handlers, name) reply(tag, :ok) loop(parent, name, handlers, debug, hib) {:DOWN, ref, :process, _pid, reason} = other -> case handle_down(ref, reason, handlers, name) do {:ok, handlers} -> loop(parent, name, handlers, debug, false) :error -> {hib, handlers} = server_info(other, handlers, name) loop(parent, name, handlers, debug, hib) end {_from, tag, {:call, handler, query}} -> {hib, reply, handlers} = server_call(handler, query, handlers, name) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, {:add_handler, handler, args}} -> {hib, reply, handlers} = server_add_handler(handler, args, handlers) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, {:add_mon_handler, handler, args, notify}} -> {hib, reply, handlers} = server_add_mon_handler(handler, args, handlers, notify) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, {:add_process_handler, pid, notify}} -> {hib, reply, handlers} = server_add_process_handler(pid, handlers, notify) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, {:delete_handler, handler, args}} -> {reply, handlers} = server_remove_handler(handler, args, handlers, name) reply(tag, reply) loop(parent, name, handlers, debug, false) {_from, tag, {:swap_handler, handler1, args1, handler2, args2}} -> {hib, reply, handlers} = server_swap_handler(handler1, args1, handler2, args2, handlers, nil, name) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, {:swap_mon_handler, handler1, args1, handler2, args2, mon}} -> {hib, reply, handlers} = server_swap_handler(handler1, args1, handler2, args2, handlers, mon, name) reply(tag, reply) loop(parent, name, handlers, debug, hib) {_from, tag, :stop} -> try do server_terminate(:normal, parent, handlers, name) catch :exit, :normal -> :ok end reply(tag, :ok) {_from, tag, :which_handlers} -> reply(tag, server_which_handlers(handlers)) loop(parent, name, handlers, debug, false) {_from, tag, :get_modules} -> reply(tag, server_get_modules(handlers)) loop(parent, name, handlers, debug, false) other -> {hib, handlers} = server_info(other, handlers, name) loop(parent, name, handlers, debug, hib) end end ## System callbacks @doc false def system_continue(parent, debug, [name, handlers, hib]) do loop(parent, name, handlers, debug, hib) end @doc false def system_terminate(reason, parent, _debug, [name, handlers, _hib]) do server_terminate(reason, parent, handlers, name) end @doc false def system_code_change([name, handlers, hib], module, old_vsn, extra) do handlers = for handler <- handlers do if handler(handler, :module) == module do {:ok, state} = module.code_change(old_vsn, handler(handler, :state), extra) handler(handler, state: state) else handler end end {:ok, [name, handlers, hib]} end @doc false def system_get_state([_name, handlers, _hib]) do tuples = for handler(module: mod, id: id, state: state) <- handlers do {mod, id, state} end {:ok, tuples} end @doc false def system_replace_state(fun, [name, handlers, hib]) do {handlers, states} = :lists.unzip(for handler <- handlers do handler(module: mod, id: id, state: state) = handler cur = {mod, id, state} try do new = {^mod, ^id, new_state} = fun.(cur) {handler(handler, state: new_state), new} catch _, _ -> {handler, cur} end end) {:ok, states, [name, handlers, hib]} end @doc false def format_status(opt, status_data) do [pdict, sys_state, parent, _debug, [name, handlers, _hib]] = status_data header = :gen.format_status_header('Status for event handler', name) formatted = for handler <- handlers do handler(module: module, state: state) = handler if function_exported?(module, :format_status, 2) do try do state = module.format_status(opt, [pdict, state]) handler(handler, state: state) catch _, _ -> handler end else handler end end [header: header, data: [{'Status', sys_state}, {'Parent', parent}], items: {'Installed handlers', formatted}] end ## Loop helpers defp print_event(dev, {:in, msg}, name) do case msg do {:notify, event} -> IO.puts dev, "*DBG* #{inspect name} got event #{inspect event}" {_, _, {:call, handler, query}} -> IO.puts dev, "*DBG* #{inspect name} (handler #{inspect handler}) got call #{inspect query}" _ -> IO.puts dev, "*DBG* #{inspect name} got #{inspect msg}" end end defp print_event(dev, dbg, name) do IO.puts dev, "*DBG* #{inspect name}: #{inspect dbg}" end defp server_add_handler({module, id}, args, handlers) do handler = handler(module: module, id: {module, id}) do_add_handler(module, handler, args, handlers, :ok) end defp server_add_handler(module, args, handlers) do handler = handler(module: module, id: module) do_add_handler(module, handler, args, handlers, :ok) end defp server_add_mon_handler({module, id}, args, handlers, notify) do ref = Process.monitor(notify) handler = handler(module: module, id: {module, id}, pid: notify, ref: ref) do_add_handler(module, handler, args, handlers, :ok) end defp server_add_mon_handler(module, args, handlers, notify) do ref = Process.monitor(notify) handler = handler(module: module, id: module, pid: notify, ref: ref) do_add_handler(module, handler, args, handlers, :ok) end defp server_add_process_handler(pid, handlers, notify) do ref = Process.monitor(pid) handler = handler(module: GenEvent.Stream, id: {self(), ref}, pid: notify, ref: ref) do_add_handler(GenEvent.Stream, handler, {pid, ref}, handlers, {self(), ref}) end defp server_remove_handler(module, args, handlers, name) do do_take_handler(module, args, handlers, name, :remove, :normal) end defp server_swap_handler(module1, args1, module2, args2, handlers, sup, name) do {state, handlers} = do_take_handler(module1, args1, handlers, name, :swapped, {:swapped, module2, sup}) if sup do server_add_mon_handler(module2, {args2, state}, handlers, sup) else server_add_handler(module2, {args2, state}, handlers) end end defp server_info(event, handlers, name) do handlers = :lists.reverse(handlers) server_notify(event, :handle_info, handlers, name, handlers, [], false) end defp server_event(mode, event, handlers, name) do {handlers, streams} = server_split_process_handlers(mode, event, handlers, [], []) {hib, handlers} = server_notify(event, :handle_event, handlers, name, handlers, [], false) {hib, server_collect_process_handlers(mode, event, streams, handlers, name)} end defp server_split_process_handlers(mode, event, [handler|t], handlers, streams) do case handler(handler, :id) do {pid, _ref} when is_pid(pid) -> server_process_notify(mode, event, handler) server_split_process_handlers(mode, event, t, handlers, [handler|streams]) _ -> server_split_process_handlers(mode, event, t, [handler|handlers], streams) end end defp server_split_process_handlers(_mode, _event, [], handlers, streams) do {handlers, streams} end defp server_process_notify(mode, event, handler(state: {pid, ref})) do send pid, {self(), {self(), ref}, {mode_to_tag(mode), event}} end defp mode_to_tag(:ack), do: :ack_notify defp mode_to_tag(:sync), do: :sync_notify defp mode_to_tag(:async), do: :notify defp server_notify(event, fun, [handler|t], name, handlers, acc, hib) do case server_update(handler, fun, event, name, handlers) do {new_hib, handler} -> server_notify(event, fun, t, name, handlers, [handler|acc], hib or new_hib) :error -> server_notify(event, fun, t, name, handlers, acc, hib) end end defp server_notify(_, _, [], _, _, acc, hib) do {hib, acc} end defp server_update(handler, fun, event, name, _handlers) do handler(module: module, state: state) = handler case do_handler(module, fun, [event, state]) do {:ok, res} -> case res do {:ok, state} -> {false, handler(handler, state: state)} {:ok, state, :hibernate} -> {true, handler(handler, state: state)} :remove_handler -> do_terminate(handler, :remove_handler, event, name, :normal) :error other -> reason = {:bad_return_value, other} do_terminate(handler, {:error, reason}, event, name, reason) :error end {:error, reason} -> do_terminate(handler, {:error, reason}, event, name, reason) :error end end defp server_collect_process_handlers(:async, event, [handler|t], handlers, name) do server_collect_process_handlers(:async, event, t, [handler|handlers], name) end defp server_collect_process_handlers(mode, event, [handler|t], handlers, name) when mode in [:sync, :ack] do handler(ref: ref, id: id) = handler receive do {^ref, :ok} -> server_collect_process_handlers(mode, event, t, [handler|handlers], name) {_from, tag, {:delete_handler, ^id, args}} -> do_terminate(handler, args, :remove, name, :normal) reply(tag, :ok) server_collect_process_handlers(mode, event, t, handlers, name) {:DOWN, ^ref, _, _, reason} -> do_terminate(handler, {:stop, reason}, :DOWN, name, :shutdown) server_collect_process_handlers(mode, event, t, handlers, name) end end defp server_collect_process_handlers(_mode, _event, [], handlers, _name) do handlers end defp server_call(module, query, handlers, name) do case :lists.keyfind(module, handler(:id) + 1, handlers) do false -> {false, {:error, :not_found}, handlers} handler -> case server_call_update(handler, query, name, handlers) do {{hib, handler}, reply} -> {hib, reply, :lists.keyreplace(module, handler(:id) + 1, handlers, handler)} {:error, reply} -> {false, reply, :lists.keydelete(module, handler(:id) + 1, handlers)} end end end defp server_call_update(handler, query, name, _handlers) do handler(module: module, state: state) = handler case do_handler(module, :handle_call, [query, state]) do {:ok, res} -> case res do {:ok, reply, state} -> {{false, handler(handler, state: state)}, reply} {:ok, reply, state, :hibernate} -> {{true, handler(handler, state: state)}, reply} {:remove_handler, reply} -> do_terminate(handler, :remove_handler, query, name, :normal) {:error, reply} other -> reason = {:bad_return_value, other} do_terminate(handler, {:error, reason}, query, name, reason) {:error, {:error, reason}} end {:error, reason} -> do_terminate(handler, {:error, reason}, query, name, reason) {:error, {:error, reason}} end end defp server_get_modules(handlers) do (for handler(module: module) <- handlers, do: module) |> :ordsets.from_list |> :ordsets.to_list end defp server_which_handlers(handlers) do for handler(id: id) <- handlers, do: id end defp server_terminate(reason, _parent, handlers, name) do _ = for handler <- handlers do do_terminate(handler, :stop, :stop, name, :shutdown) end exit(reason) end defp reply({from, ref}, msg) do send from, {ref, msg} end defp handle_down(ref, reason, handlers, name) do case :lists.keyfind(ref, handler(:ref) + 1, handlers) do false -> :error handler -> do_terminate(handler, {:stop, reason}, :DOWN, name, :shutdown) {:ok, :lists.keydelete(ref, handler(:ref) + 1, handlers)} end end defp do_add_handler(module, handler, arg, handlers, succ) do case :lists.keyfind(handler(handler, :id), handler(:id) + 1, handlers) do false -> case do_handler(module, :init, [arg]) do {:ok, res} -> case res do {:ok, state} -> {false, succ, [handler(handler, state: state)|handlers]} {:ok, state, :hibernate} -> {true, succ, [handler(handler, state: state)|handlers]} {:error, _} = error -> {false, error, handlers} other -> {false, {:error, {:bad_return_value, other}}, handlers} end {:error, _} = error -> {false, error, handlers} end _ -> {false, {:error, :already_present}, handlers} end end defp do_take_handler(module, args, handlers, name, last_in, reason) do case :lists.keytake(module, handler(:id) + 1, handlers) do {:value, handler, handlers} -> {do_terminate(handler, args, last_in, name, reason), handlers} false -> {{:error, :not_found}, handlers} end end defp do_terminate(handler, arg, last_in, name, reason) do handler(module: module, state: state) = handler res = case do_handler(module, :terminate, [arg, state]) do {:ok, res} -> res {:error, _} = error -> error end report_terminate(handler, reason, state, last_in, name) res end defp do_handler(mod, fun, args) do try do apply(mod, fun, args) catch :throw, val -> {:ok, val} :error, val -> {:error, {val, System.stacktrace}} :exit, val -> {:error, val} else res -> {:ok, res} end end defp report_terminate(handler, reason, state, last_in, name) do report_error(handler, reason, state, last_in, name) if ref = handler(handler, :ref) do Process.demonitor(ref, [:flush]) end if pid = handler(handler, :pid) do send pid, {:gen_event_EXIT, handler(handler, :id), reason} end end defp report_error(_handler, :normal, _, _, _), do: :ok defp report_error(_handler, :shutdown, _, _, _), do: :ok defp report_error(_handler, {:swapped, _, _}, _, _, _), do: :ok defp report_error(handler, reason, state, last_in, name) do reason = case reason do {:undef, [{m, f, a, _}|_]=mfas} -> cond do :code.is_loaded(m) === false -> {:"module could not be loaded", mfas} function_exported?(m, f, length(a)) -> reason true -> {:"function not exported", mfas} end _ -> reason end formatted = report_status(handler, state) :error_logger.error_msg( '** gen_event handler ~p crashed.~n' ++ '** Was installed in ~p~n' ++ '** Last event was: ~p~n' ++ '** When handler state == ~p~n' ++ '** Reason == ~p~n', [handler(handler, :id), name, last_in, formatted, reason]) end defp report_status(handler(module: module), state) do if function_exported?(module, :format_status, 2) do try do module.format_status(:terminate, [Process.get(), state]) catch _, _ -> state end else state end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/gen_event/000077500000000000000000000000001254730255300216775ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/gen_event/stream.ex000066400000000000000000000104471254730255300235360ustar00rootroot00000000000000defmodule GenEvent.Stream do @moduledoc """ Defines a `GenEvent` stream. This is a struct returned by `stream/2`. The struct is public and contains the following fields: * `:manager` - the manager reference given to `GenEvent.stream/2` * `:timeout` - the timeout between events, defaults to `:infinity` """ defstruct manager: nil, timeout: :infinity @type t :: %__MODULE__{ manager: GenEvent.manager, timeout: timeout} @doc false def init({_pid, _ref} = state) do {:ok, state} end @doc false def handle_event(event, _state) do exit({:bad_event, event}) end @doc false def handle_call(msg, _state) do # We do this to trick dialyzer to not complain about non-local returns. case :random.uniform(1) do 1 -> exit({:bad_call, msg}) 2 -> {:remove_handler, :ok} end end @doc false def handle_info(_msg, state) do {:ok, state} end @doc false def terminate(_reason, _state) do :ok end @doc false def code_change(_old, state, _extra) do {:ok, state} end end defimpl Enumerable, for: GenEvent.Stream do def reduce(stream, acc, fun) do start_fun = fn() -> start(stream) end next_fun = &next(stream, &1) stop_fun = &stop(stream, &1) Stream.resource(start_fun, next_fun, stop_fun).(acc, wrap_reducer(fun)) end def count(_stream) do {:error, __MODULE__} end def member?(_stream, _item) do {:error, __MODULE__} end defp wrap_reducer(fun) do fn {:ack, manager, ref, event}, acc -> send manager, {ref, :ok} fun.(event, acc) {:async, _manager, _ref, event}, acc -> fun.(event, acc) {:sync, manager, ref, event}, acc -> try do fun.(event, acc) after send manager, {ref, :ok} end end end defp start(%{manager: manager} = stream) do try do {:ok, {pid, ref}} = :gen.call(manager, self(), {:add_process_handler, self(), self()}, :infinity) mon_ref = Process.monitor(pid) {pid, ref, mon_ref} catch :exit, reason -> exit({reason, {__MODULE__, :start, [stream]}}) end end defp next(%{timeout: timeout} = stream, {pid, ref, mon_ref} = acc) do self = self() receive do # Got an async event. {_from, {^pid, ^ref}, {:notify, event}} -> {[{:async, pid, ref, event}], acc} # Got a sync event. {_from, {^pid, ^ref}, {:sync_notify, event}} -> {[{:sync, pid, ref, event}], acc} # Got an ack event. {_from, {^pid, ^ref}, {:ack_notify, event}} -> {[{:ack, pid, ref, event}], acc} # The handler was removed. Stop iteration, resolve the # event later. We need to demonitor now, otherwise DOWN # appears with higher priority in the shutdown process. {:gen_event_EXIT, {^pid, ^ref}, _reason} = event -> Process.demonitor(mon_ref, [:flush]) send(self, event) {:halt, {:removed, acc}} # The manager died. Stop iteration, resolve the event later. {:DOWN, ^mon_ref, _, _, _} = event -> send(self, event) {:halt, {:removed, acc}} after timeout -> exit({:timeout, {__MODULE__, :next, [stream, acc]}}) end end # If we reach this branch, we know the handler was already # removed, so we don't trigger a request for doing so. defp stop(stream, {:removed, {pid, ref, mon_ref} = acc}) do case wait_for_handler_removal(pid, ref, mon_ref) do :ok -> flush_events(ref) {:error, reason} -> exit({reason, {__MODULE__, :stop, [stream, acc]}}) end end # If we reach this branch, the handler was not removed yet, # so we trigger a request for doing so. defp stop(stream, {pid, ref, _} = acc) do _ = GenEvent.remove_handler(pid, {pid, ref}, :shutdown) stop(stream, {:removed, acc}) end defp wait_for_handler_removal(pid, ref, mon_ref) do receive do {:gen_event_EXIT, {^pid, ^ref}, _reason} -> Process.demonitor(mon_ref, [:flush]) :ok {:DOWN, ^mon_ref, _, _, reason} -> {:error, reason} end end defp flush_events(ref) do receive do {_from, {_pid, ^ref}, {notify, _event}} when notify in [:notify, :ack_notify, :sync_notify] -> flush_events(ref) after 0 -> :ok end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/gen_server.ex000066400000000000000000000405441254730255300224310ustar00rootroot00000000000000defmodule GenServer do @moduledoc """ A behaviour module for implementing the server of a client-server relation. A GenServer is a process as any other Elixir process and it can be used to keep state, execute code asynchronously and so on. The advantage of using a generic server process (GenServer) implemented using this module is that it will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree. ## Example The GenServer behaviour abstracts the common client-server interaction. Developers are only required to implement the callbacks and functionality they are interested in. Let's start with a code example and then explore the available callbacks. Imagine we want a GenServer that works like a stack, allowing us to push and pop items: defmodule Stack do use GenServer # Callbacks def handle_call(:pop, _from, [h|t]) do {:reply, h, t} end def handle_cast({:push, item}, state) do {:noreply, [item|state]} end end # Start the server {:ok, pid} = GenServer.start_link(Stack, [:hello]) # This is the client GenServer.call(pid, :pop) #=> :hello GenServer.cast(pid, {:push, :world}) #=> :ok GenServer.call(pid, :pop) #=> :world We start our `Stack` by calling `start_link/3`, passing the module with the server implementation and its initial argument (a list representing the stack containing the item `:hello`). We can primarily interact with the server by sending two types of messages. **call** messages expect a reply from the server (and are therefore synchronous) while **cast** messages do not. Every time you do a `GenServer.call/3`, the client will send a message that must be handled by the `handle_call/3` callback in the GenServer. A `cast/2` message must be handled by `handle_cast/2`. ## Callbacks There are 6 callbacks required to be implemented in a `GenServer`. By adding `use GenServer` to your module, Elixir will automatically define all 6 callbacks for you, leaving it up to you to implement the ones you want to customize. The callbacks are: * `init(args)` - invoked when the server is started. It must return: - `{:ok, state}` - `{:ok, state, timeout}` - `{:ok, state, :hibernate}` - `:ignore` - `{:stop, reason}` * `handle_call(msg, {from, ref}, state)` and `handle_cast(msg, state)` - invoked to handle call (sync) and cast (async) messages. It must return: - `{:reply, reply, new_state}` - `{:reply, reply, new_state, timeout}` - `{:reply, reply, new_state, :hibernate}` - `{:noreply, new_state}` - `{:noreply, new_state, timeout}` - `{:noreply, new_state, :hibernate}` - `{:stop, reason, new_state}` - `{:stop, reason, reply, new_state}` * `handle_info(msg, state)` - invoked to handle all other messages which are received by the process. It must return: - `{:noreply, state}` - `{:noreply, state, timeout}` - `{:stop, reason, state}` * `terminate(reason, state)` - called when the server is about to terminate, useful for cleaning up. It must return `:ok`. * `code_change(old_vsn, state, extra)` - called when the application code is being upgraded live (hot code swapping). It must return: - `{:ok, new_state}` - `{:error, reason}` ## Name Registration Both `start_link/3` and `start/3` support the `GenServer` to register a name on start via the `:name` option. Registered names are also automatically cleaned up on termination. The supported values are: * an atom - the GenServer is registered locally with the given name using `Process.register/2`. * `{:global, term}`- the GenServer is registered globally with the given term using the functions in the `:global` module. * `{:via, module, term}` - the GenServer is registered with the given mechanism and name. The `:via` option expects a module name to control the registration mechanism alongside a name which can be any term. For example, we could start and register our Stack server locally as follows: # Start the server and register it locally with name MyStack {:ok, _} = GenServer.start_link(Stack, [:hello], name: MyStack) # Now messages can be sent directly to MyStack GenServer.call(MyStack, :pop) #=> :hello Once the server is started, the remaining functions in this module (`call/3`, `cast/2`, and friends) will also accept an atom, or any `:global` or `:via` tuples. In general, the following formats are supported: * a `pid` * an `atom` if the server is locally registered * `{atom, node}` if the server is locally registered at another node * `{:global, term}` if the server is globally registered * `{:via, module, name}` if the server is registered through an alternative registry ## Client / Server APIs Although in the example above we have used `GenServer.start_link/3` and friends to directly start and communicate with the server, most of the time we don't call the `GenServer` functions directly. Instead, we wrap the calls in new functions representing the public API of the server. Here is a better implementation of our Stack module: defmodule Stack do use GenServer # Client def start_link(default) do GenServer.start_link(__MODULE__, default) end def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server (callbacks) def handle_call(:pop, _from, [h|t]) do {:reply, h, t} end def handle_call(request, from, state) do # Call the default implementation from GenServer super(request, from, state) end def handle_cast({:push, item}, state) do {:noreply, [item|state]} end def handle_cast(request, state) do super(request, state) end end In practice, it is common to have both server and client functions in the same module. If the server and/or client implementations are growing complex, you may want to have them in different modules. ## Learn more If you wish to find out more about gen servers, Elixir getting started guides provide a tutorial-like introduction. The documentation and links in Erlang can also provide extra insight. * http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html * http://www.erlang.org/doc/man/gen_server.html * http://www.erlang.org/doc/design_principles/gen_server_concepts.html * http://learnyousomeerlang.com/clients-and-servers """ @typedoc "Return values of `start*` functions" @type on_start :: {:ok, pid} | :ignore | {:error, {:already_started, pid} | term} @typedoc "The GenServer name" @type name :: atom | {:global, term} | {:via, module, term} @typedoc "Options used by the `start*` functions" @type options :: [debug: debug, name: name, timeout: timeout, spawn_opt: Process.spawn_opt] @typedoc "debug options supported by the `start*` functions" @type debug :: [:trace | :log | :statistics | {:log_to_file, Path.t}] @typedoc "The server reference" @type server :: pid | name | {atom, node} @doc false defmacro __using__(_) do quote location: :keep do @behaviour :gen_server @doc false def init(args) do {:ok, args} end @doc false def handle_call(msg, _from, state) do # We do this to trick dialyzer to not complain about non-local returns. case :random.uniform(1) do 1 -> exit({:bad_call, msg}) 2 -> {:noreply, state} end end @doc false def handle_info(_msg, state) do {:noreply, state} end @doc false def handle_cast(msg, state) do # We do this to trick dialyzer to not complain about non-local returns. case :random.uniform(1) do 1 -> exit({:bad_cast, msg}) 2 -> {:noreply, state} end end @doc false def terminate(_reason, _state) do :ok end @doc false def code_change(_old, state, _extra) do {:ok, state} end defoverridable [init: 1, handle_call: 3, handle_info: 2, handle_cast: 2, terminate: 2, code_change: 3] end end @doc """ Starts a `GenServer` process linked to the current process. This is often used to start the `GenServer` as part of a supervision tree. Once the server is started, it calls the `init/1` function in the given `module` passing the given `args` to initialize it. To ensure a synchronized start-up procedure, this function does not return until `init/1` has returned. Note that a `GenServer` started with `start_link/3` is linked to the parent process and will exit in case of crashes. The GenServer will also exit due to the `:normal` reasons in case it is configured to trap exits in the `init/1` callback. ## Options The `:name` option is used for name registration as described in the module documentation. If the option `:timeout` option is present, the server is allowed to spend the given milliseconds initializing or it will be terminated and the start function will return `{:error, :timeout}`. If the `:debug` option is present, the corresponding function in the [`:sys` module](http://www.erlang.org/doc/man/sys.html) will be invoked. If the `:spawn_opt` option is present, its value will be passed as options to the underlying process as in `Process.spawn/4`. ## Return values If the server is successfully created and initialized, the function returns `{:ok, pid}`, where pid is the pid of the server. If a process with the specified server name already exists, the function returns `{:error, {:already_started, pid}}` with the pid of that process. If the `init/1` callback fails with `reason`, the function returns `{:error, reason}`. Otherwise, if it returns `{:stop, reason}` or `:ignore`, the process is terminated and the function returns `{:error, reason}` or `:ignore`, respectively. """ @spec start_link(module, any, options) :: on_start def start_link(module, args, options \\ []) when is_atom(module) and is_list(options) do do_start(:link, module, args, options) end @doc """ Starts a `GenServer` process without links (outside of a supervision tree). See `start_link/3` for more information. """ @spec start(module, any, options) :: on_start def start(module, args, options \\ []) when is_atom(module) and is_list(options) do do_start(:nolink, module, args, options) end defp do_start(link, module, args, options) do case Keyword.pop(options, :name) do {nil, opts} -> :gen.start(:gen_server, link, module, args, opts) {atom, opts} when is_atom(atom) -> :gen.start(:gen_server, link, {:local, atom}, module, args, opts) {other, opts} when is_tuple(other) -> :gen.start(:gen_server, link, other, module, args, opts) end end @doc """ Makes a synchronous call to the `server` and waits for its reply. The client sends the given `request` to the server and waits until a reply arrives or a timeout occurs. `handle_call/3` will be called on the server to handle the request. The server can be any of the values described in the `Name Registration` section of the module documentation. ## Timeouts The `timeout` is an integer greater than zero which specifies how many milliseconds to wait for a reply, or the atom `:infinity` to wait indefinitely. The default value is 5000. If no reply is received within the specified time, the function call fails. If the caller catches the failure and continues running, and the server is just late with the reply, it may arrive at any time later into the caller's message queue. The caller must in this case be prepared for this and discard any such garbage messages that are two element tuples with a reference as the first element. """ @spec call(server, term, timeout) :: term def call(server, request, timeout \\ 5000) do try do :gen.call(server, :"$gen_call", request, timeout) catch :exit, reason -> exit({reason, {__MODULE__, :call, [server, request, timeout]}}) else {:ok, res} -> res end end @doc """ Sends an asynchronous request to the `server`. This function returns `:ok` without waiting for the destination `server` to handle the message. Therefore it is unknown whether the destination `server` successfully handled the message. If the `server` is an atom without an associated process an `ArgumentError` is raised. In all other cases the function returns `:ok` regardless of whether the destination `server` (or node) exists. Note that `{name, node()}` can be used when an exception is not desired if no process is locally associated with the atom `name`. `handle_cast/2` will be called on the server to handle the request. In case the `server` is on a node which is not yet connected to the caller one, the call is going to block until a connection happens. This is different than the behaviour in OTP's `:gen_server` where the message is sent by another process in this case, which could cause messages to other nodes to arrive out of order. """ @spec cast(server, term) :: :ok def cast(server, request) def cast({:global, name}, request) do try do :global.send(name, cast_msg(request)) :ok catch _, _ -> :ok end end def cast({:via, mod, name}, request) do try do mod.send(name, cast_msg(request)) :ok catch _, _ -> :ok end end def cast({name, node}, request) when is_atom(name) and is_atom(node), do: do_send({name, node}, cast_msg(request)) def cast(dest, request) when is_atom(dest) or is_pid(dest), do: do_send(dest, cast_msg(request)) @doc """ Casts all servers locally registered as `name` at the specified nodes. The function returns immediately and ignores nodes that do not exist, or where the server name does not exist. See `multi_call/4` for more information. """ @spec abcast([node], name :: atom, term) :: :abcast def abcast(nodes \\ nodes(), name, request) when is_list(nodes) and is_atom(name) do msg = cast_msg(request) _ = for node <- nodes, do: do_send({name, node}, msg) :abcast end defp cast_msg(req) do {:"$gen_cast", req} end defp do_send(dest, msg) do send(dest, msg) :ok end @doc """ Calls all servers locally registered as `name` at the specified `nodes`. The `request` is first sent to every node and then we wait for the replies. This function returns a tuple containing the node and its reply as first element and all bad nodes as second element. The bad nodes is a list of nodes that either did not exist, or where a server with the given `name` did not exist or did not reply. Nodes is a list of node names to which the request is sent. The default value is the list of all known nodes. To avoid that late answers (after the timeout) pollute the caller's message queue, a middleman process is used to do the actual calls. Late answers will then be discarded when they arrive to a terminated process. """ @spec multi_call([node], name :: atom, term, timeout) :: {replies :: [{node, term}], bad_nodes :: [node]} def multi_call(nodes \\ nodes(), name, request, timeout \\ :infinity) do :gen_server.multi_call(nodes, name, request, timeout) end @doc """ Replies to a client. This function can be used by a server to explicitly send a reply to a client that called `call/3` or `multi_call/4`. When the reply cannot be defined in the return value of `handle_call/3`. The `client` must be the `from` argument (the second argument) received in `handle_call/3` callbacks. Reply is an arbitrary term which will be given back to the client as the return value of the call. This function always returns `:ok`. """ @spec reply({pid, reference}, term) :: :ok def reply(client, reply) def reply({to, tag}, reply) do try do send(to, {tag, reply}) :ok catch _, _ -> :ok end end @compile {:inline, [nodes: 0]} defp nodes do [node()|:erlang.nodes()] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/hash_dict.ex000066400000000000000000000160061254730255300222140ustar00rootroot00000000000000defmodule HashDict do @moduledoc """ A key-value store. The `HashDict` is represented internally as a struct, therefore `%HashDict{}` can be used whenever there is a need to match on any `HashDict`. Note though the struct fields are private and must not be accessed directly. Instead, use the functions on this or in the `Dict` module. Implementation-wise, `HashDict` is implemented using tries, which grows in space as the number of keys grows, working well with both small and large set of keys. For more information about the functions and their APIs, please consult the `Dict` module. """ use Dict @node_bitmap 0b111 @node_shift 3 @node_size 8 @node_template :erlang.make_tuple(@node_size, []) @opaque t :: %__MODULE__{size: non_neg_integer, root: term} @doc false defstruct size: 0, root: @node_template # Inline common instructions @compile :inline_list_funcs @compile {:inline, key_hash: 1, key_mask: 1, key_shift: 1} @doc """ Creates a new empty dict. """ @spec new :: Dict.t def new do %HashDict{} end def put(%HashDict{root: root, size: size}, key, value) do {root, counter} = do_put(root, key, value, key_hash(key)) %HashDict{root: root, size: size + counter} end def update!(%HashDict{root: root, size: size} = dict, key, fun) when is_function(fun, 1) do {root, counter} = do_update(root, key, fn -> raise KeyError, key: key, term: dict end, fun, key_hash(key)) %HashDict{root: root, size: size + counter} end def update(%HashDict{root: root, size: size}, key, initial, fun) when is_function(fun, 1) do {root, counter} = do_update(root, key, fn -> initial end, fun, key_hash(key)) %HashDict{root: root, size: size + counter} end def fetch(%HashDict{root: root}, key) do do_fetch(root, key, key_hash(key)) end def delete(dict, key) do case dict_delete(dict, key) do {dict, _value} -> dict :error -> dict end end def pop(dict, key, default \\ nil) do case dict_delete(dict, key) do {dict, value} -> {value, dict} :error -> {default, dict} end end def size(%HashDict{size: size}) do size end @doc false def reduce(%HashDict{root: root}, acc, fun) do do_reduce(root, acc, fun, @node_size, fn {:suspend, acc} -> {:suspended, acc, &{:done, elem(&1, 1)}} {:halt, acc} -> {:halted, acc} {:cont, acc} -> {:done, acc} end) end ## General helpers @doc false def dict_delete(%HashDict{root: root, size: size}, key) do case do_delete(root, key, key_hash(key)) do {root, value} -> {%HashDict{root: root, size: size - 1}, value} :error -> :error end end ## Dict manipulation defp do_fetch(node, key, hash) do index = key_mask(hash) case elem(node, index) do [^key|v] -> {:ok, v} {^key, v, _} -> {:ok, v} {_, _, n} -> do_fetch(n, key, key_shift(hash)) _ -> :error end end defp do_put(node, key, value, hash) do index = key_mask(hash) case elem(node, index) do [] -> {put_elem(node, index, [key|value]), 1} [^key|_] -> {put_elem(node, index, [key|value]), 0} [k|v] -> n = put_elem(@node_template, key_mask(key_shift(hash)), [key|value]) {put_elem(node, index, {k, v, n}), 1} {^key, _, n} -> {put_elem(node, index, {key, value, n}), 0} {k, v, n} -> {n, counter} = do_put(n, key, value, key_shift(hash)) {put_elem(node, index, {k, v, n}), counter} end end defp do_update(node, key, initial, fun, hash) do index = key_mask(hash) case elem(node, index) do [] -> {put_elem(node, index, [key|initial.()]), 1} [^key|value] -> {put_elem(node, index, [key|fun.(value)]), 0} [k|v] -> n = put_elem(@node_template, key_mask(key_shift(hash)), [key|initial.()]) {put_elem(node, index, {k, v, n}), 1} {^key, value, n} -> {put_elem(node, index, {key, fun.(value), n}), 0} {k, v, n} -> {n, counter} = do_update(n, key, initial, fun, key_shift(hash)) {put_elem(node, index, {k, v, n}), counter} end end defp do_delete(node, key, hash) do index = key_mask(hash) case elem(node, index) do [] -> :error [^key|value] -> {put_elem(node, index, []), value} [_|_] -> :error {^key, value, n} -> {put_elem(node, index, do_compact_node(n)), value} {k, v, n} -> case do_delete(n, key, key_shift(hash)) do {@node_template, value} -> {put_elem(node, index, [k|v]), value} {n, value} -> {put_elem(node, index, {k, v, n}), value} :error -> :error end end end Enum.each 0..(@node_size - 1), fn index -> defp do_compact_node(node) when elem(node, unquote(index)) != [] do case elem(node, unquote(index)) do [k|v] -> case put_elem(node, unquote(index), []) do @node_template -> [k|v] n -> {k, v, n} end {k, v, n} -> {k, v, put_elem(node, unquote(index), do_compact_node(n))} end end end ## Dict reduce defp do_reduce_each(_node, {:halt, acc}, _fun, _next) do {:halted, acc} end defp do_reduce_each(node, {:suspend, acc}, fun, next) do {:suspended, acc, &do_reduce_each(node, &1, fun, next)} end defp do_reduce_each([], acc, _fun, next) do next.(acc) end defp do_reduce_each([k|v], {:cont, acc}, fun, next) do next.(fun.({k, v}, acc)) end defp do_reduce_each({k, v, n}, {:cont, acc}, fun, next) do do_reduce(n, fun.({k, v}, acc), fun, @node_size, next) end defp do_reduce(node, acc, fun, count, next) when count > 0 do do_reduce_each(:erlang.element(count, node), acc, fun, &do_reduce(node, &1, fun, count - 1, next)) end defp do_reduce(_node, acc, _fun, 0, next) do next.(acc) end ## Key operations import Bitwise defp key_hash(key) do :erlang.phash2(key) end defp key_mask(hash) do hash &&& @node_bitmap end defp key_shift(hash) do hash >>> @node_shift end end defimpl Enumerable, for: HashDict do def reduce(dict, acc, fun), do: HashDict.reduce(dict, acc, fun) def member?(dict, {k, v}), do: {:ok, match?({:ok, ^v}, HashDict.fetch(dict, k))} def member?(_dict, _), do: {:ok, false} def count(dict), do: {:ok, HashDict.size(dict)} end defimpl Access, for: HashDict do def get(dict, key) do HashDict.get(dict, key, nil) end def get_and_update(dict, key, fun) do {get, update} = fun.(HashDict.get(dict, key, nil)) {get, HashDict.put(dict, key, update)} end end defimpl Collectable, for: HashDict do def into(original) do {original, fn dict, {:cont, {k, v}} -> Dict.put(dict, k, v) dict, :done -> dict _, :halt -> :ok end} end end defimpl Inspect, for: HashDict do import Inspect.Algebra def inspect(dict, opts) do concat ["#HashDict<", Inspect.List.inspect(HashDict.to_list(dict), opts), ">"] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/hash_set.ex000066400000000000000000000153631254730255300220710ustar00rootroot00000000000000defmodule HashSet do @moduledoc """ A set store. The `HashSet` is represented internally as a struct, therefore `%HashSet{}` can be used whenever there is a need to match on any `HashSet`. Note though the struct fields are private and must not be accessed directly. Instead, use the functions on this or in the `Set` module. The `HashSet` is implemented using tries, which grows in space as the number of keys grows, working well with both small and large set of keys. For more information about the functions and their APIs, please consult the `Set` module. """ @behaviour Set @node_bitmap 0b111 @node_shift 3 @node_size 8 @node_template :erlang.make_tuple(@node_size, []) @opaque t :: %__MODULE__{size: non_neg_integer, root: term} @doc false defstruct size: 0, root: @node_template # Inline common instructions @compile :inline_list_funcs @compile {:inline, key_hash: 1, key_mask: 1, key_shift: 1} @doc """ Creates a new empty set. """ @spec new :: Set.t def new do %HashSet{} end def union(%HashSet{size: size1} = set1, %HashSet{size: size2} = set2) when size1 <= size2 do set_fold set1, set2, fn v, acc -> put(acc, v) end end def union(%HashSet{} = set1, %HashSet{} = set2) do set_fold set2, set1, fn v, acc -> put(acc, v) end end def intersection(%HashSet{} = set1, %HashSet{} = set2) do set_fold set1, %HashSet{}, fn v, acc -> if member?(set2, v), do: put(acc, v), else: acc end end def difference(%HashSet{} = set1, %HashSet{} = set2) do set_fold set2, set1, fn v, acc -> delete(acc, v) end end def to_list(set) do set_fold(set, [], &[&1|&2]) |> :lists.reverse end def equal?(%HashSet{size: size1} = set1, %HashSet{size: size2} = set2) do case size1 do ^size2 -> subset?(set1, set2) _ -> false end end def subset?(%HashSet{} = set1, %HashSet{} = set2) do reduce(set1, {:cont, true}, fn member, acc -> case member?(set2, member) do true -> {:cont, acc} _ -> {:halt, false} end end) |> elem(1) end def disjoint?(%HashSet{} = set1, %HashSet{} = set2) do reduce(set2, {:cont, true}, fn member, acc -> case member?(set1, member) do false -> {:cont, acc} _ -> {:halt, false} end end) |> elem(1) end def member?(%HashSet{root: root}, term) do do_member?(root, term, key_hash(term)) end def put(%HashSet{root: root, size: size}, term) do {root, counter} = do_put(root, term, key_hash(term)) %HashSet{root: root, size: size + counter} end def delete(%HashSet{root: root, size: size} = set, term) do case do_delete(root, term, key_hash(term)) do {:ok, root} -> %HashSet{root: root, size: size - 1} :error -> set end end @doc false def reduce(%HashSet{root: root}, acc, fun) do do_reduce(root, acc, fun, @node_size, fn {:suspend, acc} -> {:suspended, acc, &{:done, elem(&1, 1)}} {:halt, acc} -> {:halted, acc} {:cont, acc} -> {:done, acc} end) end def size(%HashSet{size: size}) do size end ## Set helpers defp set_fold(%HashSet{root: root}, acc, fun) do do_fold(root, acc, fun, @node_size) end ## Set manipulation defp do_member?(node, term, hash) do index = key_mask(hash) case elem(node, index) do [] -> false [^term|_] -> true [_] -> false [_|n] -> do_member?(n, term, key_shift(hash)) end end defp do_put(node, term, hash) do index = key_mask(hash) case elem(node, index) do [] -> {put_elem(node, index, [term]), 1} [^term|_] -> {node, 0} [t] -> n = put_elem(@node_template, key_mask(key_shift(hash)), [term]) {put_elem(node, index, [t|n]), 1} [t|n] -> {n, counter} = do_put(n, term, key_shift(hash)) {put_elem(node, index, [t|n]), counter} end end defp do_delete(node, term, hash) do index = key_mask(hash) case elem(node, index) do [] -> :error [^term] -> {:ok, put_elem(node, index, [])} [_] -> :error [^term|n] -> {:ok, put_elem(node, index, do_compact_node(n))} [t|n] -> case do_delete(n, term, key_shift(hash)) do {:ok, @node_template} -> {:ok, put_elem(node, index, [t])} {:ok, n} -> {:ok, put_elem(node, index, [t|n])} :error -> :error end end end Enum.each 0..(@node_size - 1), fn index -> defp do_compact_node(node) when elem(node, unquote(index)) != [] do case elem(node, unquote(index)) do [t] -> case put_elem(node, unquote(index), []) do @node_template -> [t] n -> [t|n] end [t|n] -> [t|put_elem(node, unquote(index), do_compact_node(n))] end end end ## Set fold defp do_fold_each([], acc, _fun), do: acc defp do_fold_each([t], acc, fun), do: fun.(t, acc) defp do_fold_each([t|n], acc, fun), do: do_fold(n, fun.(t, acc), fun, @node_size) defp do_fold(node, acc, fun, count) when count > 0 do acc = do_fold_each(:erlang.element(count, node), acc, fun) do_fold(node, acc, fun, count - 1) end defp do_fold(_node, acc, _fun, 0) do acc end ## Set reduce defp do_reduce_each(_node, {:halt, acc}, _fun, _next) do {:halted, acc} end defp do_reduce_each(node, {:suspend, acc}, fun, next) do {:suspended, acc, &do_reduce_each(node, &1, fun, next)} end defp do_reduce_each([], acc, _fun, next) do next.(acc) end defp do_reduce_each([t], {:cont, acc}, fun, next) do next.(fun.(t, acc)) end defp do_reduce_each([t|n], {:cont, acc}, fun, next) do do_reduce(n, fun.(t, acc), fun, @node_size, next) end defp do_reduce(node, acc, fun, count, next) when count > 0 do do_reduce_each(:erlang.element(count, node), acc, fun, &do_reduce(node, &1, fun, count - 1, next)) end defp do_reduce(_node, acc, _fun, 0, next) do next.(acc) end ## Key operations import Bitwise defp key_hash(key) do :erlang.phash2(key) end defp key_mask(hash) do hash &&& @node_bitmap end defp key_shift(hash) do hash >>> @node_shift end end defimpl Enumerable, for: HashSet do def reduce(set, acc, fun), do: HashSet.reduce(set, acc, fun) def member?(set, v), do: {:ok, HashSet.member?(set, v)} def count(set), do: {:ok, HashSet.size(set)} end defimpl Collectable, for: HashSet do def into(original) do {original, fn set, {:cont, x} -> HashSet.put(set, x) set, :done -> set _, :halt -> :ok end} end end defimpl Inspect, for: HashSet do import Inspect.Algebra def inspect(set, opts) do concat ["#HashSet<", Inspect.List.inspect(HashSet.to_list(set), opts), ">"] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/inspect.ex000066400000000000000000000340071254730255300217340ustar00rootroot00000000000000import Kernel, except: [inspect: 1] import Inspect.Algebra defprotocol Inspect do @moduledoc """ The `Inspect` protocol is responsible for converting any Elixir data structure into an algebra document. This document is then formatted, either in pretty printing format or a regular one. The `inspect/2` function receives the entity to be inspected followed by the inspecting options, represented by the struct `Inspect.Opts`. Inspection is done using the functions available in `Inspect.Algebra`. ## Examples Many times, inspecting a structure can be implemented in function of existing entities. For example, here is `HashSet`'s `inspect` implementation: defimpl Inspect, for: HashSet do import Inspect.Algebra def inspect(dict, opts) do concat ["#HashSet<", to_doc(HashSet.to_list(dict), opts), ">"] end end The `concat` function comes from `Inspect.Algebra` and it concatenates algebra documents together. In the example above, it is concatenating the string `"HashSet<"` (all strings are valid algebra documents that keep their formatting when pretty printed), the document returned by `Inspect.Algebra.to_doc/2` and the other string `">"`. Since regular strings are valid entities in an algebra document, an implementation of inspect may simply return a string, although that will devoid it of any pretty-printing. ## Error handling In case there is an error while your structure is being inspected, Elixir will automatically fall back to a raw representation. You can however access the underlying error by invoking the Inspect implementation directly. For example, to test Inspect.HashSet above, you can invoke it as: Inspect.HashSet.inspect(HashSet.new, Inspect.Opts.new) """ # Handle structs in Any @fallback_to_any true def inspect(thing, opts) end defimpl Inspect, for: Atom do require Macro def inspect(atom, _opts) do inspect(atom) end def inspect(false), do: "false" def inspect(true), do: "true" def inspect(nil), do: "nil" def inspect(:""), do: ":\"\"" def inspect(atom) do binary = Atom.to_string(atom) cond do valid_ref_identifier?(binary) -> if only_elixir?(binary) do binary else "Elixir." <> rest = binary rest end valid_atom_identifier?(binary) -> ":" <> binary atom in [:%{}, :{}, :<<>>, :..., :%] -> ":" <> binary atom in Macro.binary_ops or atom in Macro.unary_ops -> ":" <> binary true -> << ?:, ?", Inspect.BitString.escape(binary, ?") :: binary, ?" >> end end defp only_elixir?("Elixir." <> rest), do: only_elixir?(rest) defp only_elixir?("Elixir"), do: true defp only_elixir?(_), do: false # Detect if atom is an atom alias (Elixir.Foo.Bar.Baz) defp valid_ref_identifier?("Elixir" <> rest) do valid_ref_piece?(rest) end defp valid_ref_identifier?(_), do: false defp valid_ref_piece?(<>) when h in ?A..?Z do valid_ref_piece? valid_identifier?(t) end defp valid_ref_piece?(<<>>), do: true defp valid_ref_piece?(_), do: false # Detect if atom defp valid_atom_identifier?(<>) when h in ?a..?z or h in ?A..?Z or h == ?_ do valid_atom_piece?(t) end defp valid_atom_identifier?(_), do: false defp valid_atom_piece?(t) do case valid_identifier?(t) do <<>> -> true <> -> true <> -> true <> -> valid_atom_piece?(t) _ -> false end end defp valid_identifier?(<>) when h in ?a..?z when h in ?A..?Z when h in ?0..?9 when h == ?_ do valid_identifier? t end defp valid_identifier?(other), do: other end defimpl Inspect, for: BitString do def inspect(thing, %Inspect.Opts{binaries: bins} = opts) when is_binary(thing) do if bins == :as_strings or (bins == :infer and String.printable?(thing)) do <> else inspect_bitstring(thing, opts) end end def inspect(thing, opts) do inspect_bitstring(thing, opts) end ## Escaping @doc false def escape(other, char) do escape(other, char, <<>>) end defp escape(<< char, t :: binary >>, char, binary) do escape(t, char, << binary :: binary, ?\\, char >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?#, ?{>>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?a >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?b >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?d >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?e >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?f >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?n >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?r >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?\\ >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?t >>) end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, ?\\, ?v >>) end defp escape(<>, char, binary) do head = << h :: utf8 >> if String.printable?(head) do escape(t, char, append(head, binary)) else << byte :: size(8), h :: binary >> = head t = << h :: binary, t :: binary >> escape(t, char, << binary :: binary, escape_char(byte) :: binary >>) end end defp escape(<>, char, binary) do escape(t, char, << binary :: binary, escape_char(h) :: binary >>) end defp escape(<<>>, _char, binary), do: binary @doc false # Also used by Regex def escape_char(0) do <> end def escape_char(char) when char < 0x100 do <> = <> <> end def escape_char(char) when char < 0x10000 do <> = <> <> end def escape_char(char) when char < 0x1000000 do <> = <> <> end defp to_hex(c) when c in 0..9, do: ?0+c defp to_hex(c) when c in 10..15, do: ?A+c-10 defp append(<>, binary), do: append(t, << binary :: binary, h >>) defp append(<<>>, binary), do: binary ## Bitstrings defp inspect_bitstring(bitstring, opts) do each_bit(bitstring, opts.limit, "<<") <> ">>" end defp each_bit(_, 0, acc) do acc <> "..." end defp each_bit(<>, counter, acc) when t != <<>> do each_bit(t, decrement(counter), acc <> Integer.to_string(h) <> ", ") end defp each_bit(<>, _counter, acc) do acc <> Integer.to_string(h) end defp each_bit(<<>>, _counter, acc) do acc end defp each_bit(bitstring, _counter, acc) do size = bit_size(bitstring) <> = bitstring acc <> Integer.to_string(h) <> "::size(" <> Integer.to_string(size) <> ")" end defp decrement(:infinity), do: :infinity defp decrement(counter), do: counter - 1 end defimpl Inspect, for: List do def inspect([], _opts), do: "[]" def inspect(thing, %Inspect.Opts{char_lists: lists} = opts) do cond do lists == :as_char_lists or (lists == :infer and printable?(thing)) -> << ?', Inspect.BitString.escape(IO.chardata_to_string(thing), ?') :: binary, ?' >> keyword?(thing) -> surround_many("[", thing, "]", opts, &keyword/2) true -> surround_many("[", thing, "]", opts, &to_doc/2) end end def keyword({key, value}, opts) do concat( key_to_binary(key) <> ": ", to_doc(value, opts) ) end def keyword?([{key, _value} | rest]) when is_atom(key) do case Atom.to_char_list(key) do 'Elixir.' ++ _ -> false _ -> keyword?(rest) end end def keyword?([]), do: true def keyword?(_other), do: false ## Private defp key_to_binary(key) do case Inspect.Atom.inspect(key) do ":" <> right -> right other -> other end end defp printable?([c|cs]) when is_integer(c) and c in 32..126, do: printable?(cs) defp printable?([?\n|cs]), do: printable?(cs) defp printable?([?\r|cs]), do: printable?(cs) defp printable?([?\t|cs]), do: printable?(cs) defp printable?([?\v|cs]), do: printable?(cs) defp printable?([?\b|cs]), do: printable?(cs) defp printable?([?\f|cs]), do: printable?(cs) defp printable?([?\e|cs]), do: printable?(cs) defp printable?([?\a|cs]), do: printable?(cs) defp printable?([]), do: true defp printable?(_), do: false end defimpl Inspect, for: Tuple do def inspect({}, _opts), do: "{}" def inspect(tuple, opts) do surround_many("{", Tuple.to_list(tuple), "}", opts, &to_doc/2) end end defimpl Inspect, for: Map do def inspect(map, opts) do nest inspect(map, "", opts), 1 end def inspect(map, name, opts) do map = :maps.to_list(map) surround_many("%" <> name <> "{", map, "}", opts, traverse_fun(map)) end defp traverse_fun(list) do if Inspect.List.keyword?(list) do &Inspect.List.keyword/2 else &to_map/2 end end defp to_map({key, value}, opts) do concat( concat(to_doc(key, opts), " => "), to_doc(value, opts) ) end end defimpl Inspect, for: Integer do def inspect(thing, %Inspect.Opts{base: base}) do Integer.to_string(thing, base_to_value(base)) |> prepend_prefix(base) end defp base_to_value(base) do case base do :binary -> 2 :decimal -> 10 :octal -> 8 :hex -> 16 end end defp prepend_prefix(value, :decimal), do: value defp prepend_prefix(value, base) do prefix = case base do :binary -> "0b" :octal -> "0o" :hex -> "0x" end prefix <> value end end defimpl Inspect, for: Float do def inspect(thing, _opts) do IO.iodata_to_binary(:io_lib_format.fwrite_g(thing)) end end defimpl Inspect, for: Regex do def inspect(regex, _opts) do delim = ?/ concat ["~r", <>, regex.opts] end defp escape(bin, term), do: escape(bin, <<>>, term) defp escape(<> <> rest, buf, term), do: escape(rest, buf <> <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, buf <> <>, term) # the list of characters is from `String.printable?` impl # minus characters treated specially by regex: \s, \d, \b, \e defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<> <> rest, buf, term) do charstr = <> if String.printable?(charstr) and not c in [?\d, ?\b, ?\e] do escape(rest, buf <> charstr, term) else escape(rest, buf <> Inspect.BitString.escape_char(c), term) end end defp escape(<> <> rest, buf, term), do: escape(rest, <>, term) defp escape(<<>>, buf, _), do: buf end defimpl Inspect, for: Function do def inspect(function, _opts) do fun_info = :erlang.fun_info(function) mod = fun_info[:module] if fun_info[:type] == :external and fun_info[:env] == [] do "&#{Inspect.Atom.inspect(mod)}.#{fun_info[:name]}/#{fun_info[:arity]}" else case Atom.to_char_list(mod) do 'elixir_compiler_' ++ _ -> if function_exported?(mod, :__RELATIVE__, 0) do "#Function<#{uniq(fun_info)} in file:#{mod.__RELATIVE__}>" else default_inspect(mod, fun_info) end _ -> default_inspect(mod, fun_info) end end end defp default_inspect(mod, fun_info) do "#Function<#{uniq(fun_info)}/#{fun_info[:arity]} in " <> "#{Inspect.Atom.inspect(mod)}#{extract_name(fun_info[:name])}>" end defp extract_name([]) do "" end defp extract_name(name) do name = Atom.to_string(name) case :binary.split(name, "-", [:global]) do ["", name | _] -> "." <> name _ -> "." <> name end end defp uniq(fun_info) do Integer.to_string(fun_info[:new_index]) <> "." <> Integer.to_string(fun_info[:uniq]) end end defimpl Inspect, for: PID do def inspect(pid, _opts) do "#PID" <> IO.iodata_to_binary(:erlang.pid_to_list(pid)) end end defimpl Inspect, for: Port do def inspect(port, _opts) do IO.iodata_to_binary :erlang.port_to_list(port) end end defimpl Inspect, for: Reference do def inspect(ref, _opts) do '#Ref' ++ rest = :erlang.ref_to_list(ref) "#Reference" <> IO.iodata_to_binary(rest) end end defimpl Inspect, for: Any do def inspect(%{__struct__: struct} = map, opts) do try do struct.__struct__ rescue _ -> Inspect.Map.inspect(map, opts) else dunder -> if :maps.keys(dunder) == :maps.keys(map) do pruned = :maps.remove(:__exception__, :maps.remove(:__struct__, map)) Inspect.Map.inspect(pruned, Inspect.Atom.inspect(struct, opts), opts) else Inspect.Map.inspect(map, opts) end end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/inspect/000077500000000000000000000000001254730255300213725ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/inspect/algebra.ex000066400000000000000000000430421254730255300233300ustar00rootroot00000000000000defmodule Inspect.Opts do @moduledoc """ Defines the Inspect.Opts used by the Inspect protocol. The following fields are available: * `:structs` - when `false`, structs are not formatted by the inspect protocol, they are instead printed as maps, defaults to `true`. * `:binaries` - when `:as_strings` all binaries will be printed as strings, non-printable bytes will be escaped. When `:as_binaries` all binaries will be printed in bit syntax. When the default `:infer`, the binary will be printed as a string if it is printable, otherwise in bit syntax. * `:char_lists` - when `:as_char_lists` all lists will be printed as char lists, non-printable elements will be escaped. When `:as_lists` all lists will be printed as lists. When the default `:infer`, the list will be printed as a char list if it is printable, otherwise as list. * `:limit` - limits the number of items that are printed for tuples, bitstrings, and lists, does not apply to strings nor char lists, defaults to 50. * `:pretty` - if set to `true` enables pretty printing, defaults to `false`. * `:width` - defaults to the 80 characters, used when pretty is `true` or when printing to IO devices. * `:base` - print integers as :binary, :octal, :decimal, or :hex, defaults to :decimal * `:safe` - when `false`, failures while inspecting structs will be raised as errors instead of being wrapped in the Inspect.Error exception. This is useful when debugging failures and crashes for custom inspect implementations """ defstruct structs: true, binaries: :infer, char_lists: :infer, limit: 50, width: 80, base: :decimal, pretty: false, safe: true @type t :: %__MODULE__{ structs: boolean, binaries: :infer | :as_binaries | :as_strings, char_lists: :infer | :as_lists | :as_char_lists, limit: pos_integer | :infinity, width: pos_integer | :infinity, base: :decimal | :binary | :hex | :octal, pretty: boolean, safe: boolean} end defmodule Inspect.Error do @moduledoc """ Raised when a struct cannot be inspected. """ defexception [:message] end defmodule Inspect.Algebra do @moduledoc ~S""" A set of functions for creating and manipulating algebra documents, as described in ["Strictly Pretty" (2000) by Christian Lindig][0]. An algebra document is represented by an `Inspect.Algebra` node or a regular string. iex> Inspect.Algebra.empty :doc_nil iex> "foo" "foo" With the functions in this module, we can concatenate different elements together and render them: iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty, "foo") iex> Inspect.Algebra.format(doc, 80) ["foo"] The functions `nest/2`, `space/2` and `line/2` help you put the document together into a rigid structure. However, the document algebra gets interesting when using functions like `break/2`, which converts the given string into a line break depending on how much space there is to print. Let's glue two docs together with a break and then render it: iex> doc = Inspect.Algebra.glue("a", " ", "b") iex> Inspect.Algebra.format(doc, 80) ["a", " ", "b"] Notice the break was represented as is, because we haven't reached a line limit. Once we do, it is replaced by a newline: iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b") iex> Inspect.Algebra.format(doc, 10) ["aaaaaaaaaaaaaaaaaaaa", "\n", "b"] Finally, this module also contains Elixir related functions, a bit tied to Elixir formatting, namely `surround/3` and `surround_many/5`. ## Implementation details The original Haskell implementation of the algorithm by [Wadler][1] relies on lazy evaluation to unfold document groups on two alternatives: `:flat` (breaks as spaces) and `:break` (breaks as newlines). Implementing the same logic in a strict language such as Elixir leads to an exponential growth of possible documents, unless document groups are encoded explictly as `:flat` or `:break`. Those groups are then reduced to a simple document, where the layout is already decided, per [Lindig][0]. This implementation slightly changes the semantic of Lindig's algorithm to allow elements that belong to the same group to be printed together in the same line, even if they do not fit the line fully. This was achieved by changing `:break` to mean a possible break and `:flat` to force a flat structure. Then deciding if a break works as a newline is just a matter of checking if we have enough space until the next break that is not inside a group (which is still flat). Custom pretty printers can be implemented using the documents returned by this module and by providing their own rendering functions. [0]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.2200 [1]: http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf """ @surround_separator "," @tail_separator " |" @newline "\n" @nesting 1 @break " " # Functional interface to `doc` records @type t :: :doc_nil | :doc_line | doc_cons | doc_nest | doc_break | doc_group | binary @typep doc_cons :: {:doc_cons, t, t} defmacrop doc_cons(left, right) do quote do: {:doc_cons, unquote(left), unquote(right)} end @typep doc_nest :: {:doc_nest, t, non_neg_integer} defmacrop doc_nest(doc, indent) do quote do: {:doc_nest, unquote(doc), unquote(indent) } end @typep doc_break :: {:doc_break, binary} defmacrop doc_break(break) do quote do: {:doc_break, unquote(break)} end @typep doc_group :: {:doc_group, t} defmacrop doc_group(group) do quote do: {:doc_group, unquote(group)} end defmacrop is_doc(doc) do if Macro.Env.in_guard?(__CALLER__) do do_is_doc(doc) else var = quote do: doc quote do unquote(var) = unquote(doc) unquote(do_is_doc(var)) end end end defp do_is_doc(doc) do quote do is_binary(unquote(doc)) or unquote(doc) in [:doc_nil, :doc_line] or (is_tuple(unquote(doc)) and elem(unquote(doc), 0) in [:doc_cons, :doc_nest, :doc_break, :doc_group]) end end @doc """ Converts an Elixir structure to an algebra document according to the inspect protocol. """ @spec to_doc(any, Inspect.Opts.t) :: t def to_doc(%{__struct__: struct} = map, %Inspect.Opts{} = opts) when is_atom(struct) do if opts.structs do try do Inspect.inspect(map, opts) rescue e -> stacktrace = System.stacktrace # Because we try to raise a nice error message in case # we can't inspect a struct, there is a chance the error # message itself relies on the struct being printed, so # we need to trap the inspected messages to guarantee # we won't try to render any failed instruct when building # the error message. if Process.get(:inspect_trap) do Inspect.Map.inspect(map, opts) else try do Process.put(:inspect_trap, true) res = Inspect.Map.inspect(map, opts) res = IO.iodata_to_binary(format(res, :infinity)) exception = Inspect.Error.exception( message: "got #{inspect e.__struct__} with message " <> "`#{Exception.message(e)}` while inspecting #{res}" ) if opts.safe do Inspect.inspect(exception, opts) else reraise(exception, stacktrace) end after Process.delete(:inspect_trap) end end end else Inspect.Map.inspect(map, opts) end end def to_doc(arg, %Inspect.Opts{} = opts) do Inspect.inspect(arg, opts) end @doc """ Returns a document entity used to represent nothingness. ## Examples iex> Inspect.Algebra.empty :doc_nil """ @spec empty() :: :doc_nil def empty, do: :doc_nil @doc """ Concatenates two document entities. ## Examples iex> doc = Inspect.Algebra.concat "hello", "world" iex> Inspect.Algebra.format(doc, 80) ["hello", "world"] """ @spec concat(t, t) :: doc_cons def concat(x, y) when is_doc(x) and is_doc(y) do doc_cons(x, y) end @doc """ Concatenates a list of documents. """ @spec concat([t]) :: doc_cons def concat(docs) do folddoc(docs, &concat(&1, &2)) end @doc ~S""" Nests document entity `x` positions deep. Nesting will be appended to the line breaks. ## Examples iex> doc = Inspect.Algebra.nest(Inspect.Algebra.glue("hello", "world"), 5) iex> Inspect.Algebra.format(doc, 5) ["hello", "\n ", "world"] """ @spec nest(t, non_neg_integer) :: doc_nest def nest(x, 0) when is_doc(x) do x end def nest(x, i) when is_doc(x) and is_integer(i) do doc_nest(x, i) end @doc ~S""" Document entity representing a break. This break can be rendered as a linebreak or as spaces, depending on the `mode` of the chosen layout or the provided separator. ## Examples Let's glue two docs together with a break and then render it: iex> doc = Inspect.Algebra.glue("a", " ", "b") iex> Inspect.Algebra.format(doc, 80) ["a", " ", "b"] Notice the break was represented as is, because we haven't reached a line limit. Once we do, it is replaced by a newline: iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b") iex> Inspect.Algebra.format(doc, 10) ["aaaaaaaaaaaaaaaaaaaa", "\n", "b"] """ @spec break(binary) :: doc_break def break(s) when is_binary(s), do: doc_break(s) @spec break() :: doc_break def break(), do: doc_break(@break) @doc """ Inserts a break between two docs. See `break/1` for more info. """ @spec glue(t, t) :: doc_cons def glue(x, y), do: concat(x, concat(break, y)) @doc """ Inserts a break, passed as the second argument, between two docs, the first and the third arguments. """ @spec glue(t, binary, t) :: doc_cons def glue(x, g, y) when is_binary(g), do: concat(x, concat(break(g), y)) @doc ~S""" Returns a group containing the specified document. ## Examples iex> doc = Inspect.Algebra.group( ...> Inspect.Algebra.concat( ...> Inspect.Algebra.group( ...> Inspect.Algebra.concat( ...> "Hello,", ...> Inspect.Algebra.concat( ...> Inspect.Algebra.break, ...> "A" ...> ) ...> ) ...> ), ...> Inspect.Algebra.concat( ...> Inspect.Algebra.break, ...> "B" ...> ) ...> )) iex> Inspect.Algebra.format(doc, 80) ["Hello,", " ", "A", " ", "B"] iex> Inspect.Algebra.format(doc, 6) ["Hello,", "\n", "A", " ", "B"] """ @spec group(t) :: doc_group def group(d) when is_doc(d) do doc_group(d) end @doc """ Inserts a mandatory single space between two document entities. ## Examples iex> doc = Inspect.Algebra.space "Hughes", "Wadler" iex> Inspect.Algebra.format(doc, 80) ["Hughes", " ", "Wadler"] """ @spec space(t, t) :: doc_cons def space(x, y), do: concat(x, concat(" ", y)) @doc ~S""" Inserts a mandatory linebreak between two document entities. ## Examples iex> doc = Inspect.Algebra.line "Hughes", "Wadler" iex> Inspect.Algebra.format(doc, 80) ["Hughes", "\n", "Wadler"] """ @spec line(t, t) :: doc_cons def line(x, y), do: concat(x, concat(:doc_line, y)) @doc """ Folds a list of document entities into a document entity using a function that is passed as the first argument. ## Examples iex> doc = ["A", "B"] iex> doc = Inspect.Algebra.folddoc(doc, fn(x, y) -> ...> Inspect.Algebra.concat [x, "!", y] ...> end) iex> Inspect.Algebra.format(doc, 80) ["A", "!", "B"] """ @spec folddoc([t], ((t, t) -> t)) :: t def folddoc(list, fun) def folddoc([], _), do: empty def folddoc([doc], _), do: doc def folddoc([d|ds], fun), do: fun.(d, folddoc(ds, fun)) # Elixir conveniences @doc ~S""" Surrounds a document with characters. Puts the document between left and right enclosing and nesting it. The document is marked as a group, to show the maximum as possible concisely together. ## Examples iex> doc = Inspect.Algebra.surround "[", Inspect.Algebra.glue("a", "b"), "]" iex> Inspect.Algebra.format(doc, 3) ["[", "a", "\n ", "b", "]"] """ @spec surround(binary, t, binary) :: t def surround(left, doc, right) do group concat left, concat(nest(doc, @nesting), right) end @doc ~S""" Maps and glues a collection of items. It uses the given left and right as surrounding and a separator for each item. A limit can be passed which, once reached, stops gluing and outputs "..." instead. ## Examples iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", ...> %Inspect.Opts{limit: :infinity}, fn i, _opts -> to_string(i) end) iex> Inspect.Algebra.format(doc, 5) |> IO.iodata_to_binary "[1,\n 2,\n 3,\n 4,\n 5]" iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", ...> %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end) iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary "[1, 2, 3, ...]" iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", ...> %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end, "!") iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary "[1! 2! 3! ...]" """ @spec surround_many(binary, [any], binary, Inspect.Opts.t, (term, Inspect.Opts.t -> t), binary) :: t def surround_many(left, docs, right, opts, fun, separator \\ @surround_separator) do do_surround_many(left, docs, right, opts.limit, opts, fun, separator) end defp do_surround_many(left, [], right, _, _opts, _fun, _) do concat(left, right) end defp do_surround_many(left, docs, right, limit, _opts, fun, sep) do surround(left, do_surround_many(docs, limit, _opts, fun, sep), right) end defp do_surround_many(_, 0, _opts, _fun, _sep) do "..." end defp do_surround_many([], _limit, _opts, _fun, _sep) do :doc_nil end defp do_surround_many([h], limit, opts, fun, _sep) do fun.(h, %{opts | limit: limit}) end defp do_surround_many([h|t], limit, opts, fun, sep) when is_list(t) do limit = decrement(limit) h = fun.(h, %{opts | limit: limit}) t = do_surround_many(t, limit, opts, fun, sep) do_join(h, t, sep) end defp do_surround_many([h|t], limit, opts, fun, _sep) do limit = decrement(limit) h = fun.(h, %{opts | limit: limit}) t = fun.(t, %{opts | limit: limit}) do_join(h, t, @tail_separator) end defp do_join(:doc_nil, :doc_nil, _), do: :doc_nil defp do_join(h, :doc_nil, _), do: h defp do_join(:doc_nil, t, _), do: t defp do_join(h, t, sep), do: glue(concat(h, sep), t) defp decrement(:infinity), do: :infinity defp decrement(counter), do: counter - 1 @doc """ The formatting function. Takes the maximum width and a document to print as its arguments and returns an IO data representation of the best layout for the document to fit in the given width. """ @spec format(t, non_neg_integer | :infinity) :: iodata def format(d, w) do format(w, 0, [{0, default_mode(w), doc_group(d)}]) end defp default_mode(:infinity), do: :flat defp default_mode(_), do: :break # Record representing the document mode to be rendered: flat or broken @typep mode :: :flat | :break @spec fits?(integer, [{integer, mode, t}]) :: boolean defp fits?(w, _) when w < 0, do: false defp fits?(_, []), do: true defp fits?(_, [{_, _, :doc_line} | _]), do: true defp fits?(w, [{_, _, :doc_nil} | t]), do: fits?(w, t) defp fits?(w, [{i, m, doc_cons(x, y)} | t]), do: fits?(w, [{i, m, x} | [{i, m, y} | t]]) defp fits?(w, [{i, m, doc_nest(x, j)} | t]), do: fits?(w, [{i + j, m, x} | t]) defp fits?(w, [{i, _, doc_group(x)} | t]), do: fits?(w, [{i, :flat, x} | t]) defp fits?(w, [{_, _, s} | t]) when is_binary(s), do: fits?((w - byte_size s), t) defp fits?(w, [{_, :flat, doc_break(s)} | t]), do: fits?((w - byte_size s), t) defp fits?(_, [{_, :break, doc_break(_)} | _]), do: true @spec format(integer | :infinity, integer, [{integer, mode, t}]) :: [binary] defp format(_, _, []), do: [] defp format(w, _, [{i, _, :doc_line} | t]), do: [indent(i) | format(w, i, t)] defp format(w, k, [{_, _, :doc_nil} | t]), do: format(w, k, t) defp format(w, k, [{i, m, doc_cons(x, y)} | t]), do: format(w, k, [{i, m, x} | [{i, m, y} | t]]) defp format(w, k, [{i, m, doc_nest(x, j)} | t]), do: format(w, k, [{i + j, m, x} | t]) defp format(w, k, [{i, m, doc_group(x)} | t]), do: format(w, k, [{i, m, x} | t]) defp format(w, k, [{_, _, s} | t]) when is_binary(s), do: [s | format(w, (k + byte_size s), t)] defp format(w, k, [{_, :flat, doc_break(s)} | t]), do: [s | format(w, (k + byte_size s), t)] defp format(w, k, [{i, :break, doc_break(s)} | t]) do k = k + byte_size(s) if w == :infinity or fits?(w - k, t) do [s | format(w, k, t)] else [indent(i) | format(w, i, t)] end end defp indent(0), do: @newline defp indent(i), do: @newline <> :binary.copy(" ", i) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/integer.ex000066400000000000000000000126141254730255300217240ustar00rootroot00000000000000defmodule Integer do @moduledoc """ Functions for working with integers. """ import Bitwise @doc """ Determines if an integer is odd. Returns `true` if `n` is an odd number, otherwise `false`. Allowed in guard clauses. """ defmacro is_odd(n) do quote do: (unquote(n) &&& 1) == 1 end @doc """ Determines if an integer is even. Returns `true` if `n` is an even number, otherwise `false`. Allowed in guard clauses. """ defmacro is_even(n) do quote do: (unquote(n) &&& 1) == 0 end @doc """ Returns the ordered digits for the given non-negative integer. An optional base value may be provided representing the radix for the returned digits. ## Examples iex> Integer.digits(101) [1, 0, 1] iex> Integer.digits(58127, 2) [1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1] """ @spec digits(non_neg_integer, pos_integer) :: [non_neg_integer] def digits(n, base \\ 10) when is_integer(n) and n >= 0 and is_integer(base) and base >= 2 do do_digits(n, base, []) end defp do_digits(0, _base, []), do: [0] defp do_digits(0, _base, acc), do: acc defp do_digits(n, base, acc) do do_digits div(n, base), base, [rem(n, base) | acc] end @doc """ Returns the integer represented by the ordered digits. An optional base value may be provided representing the radix for the digits. ## Examples iex> Integer.undigits([1, 0, 1]) 101 iex> Integer.undigits([1, 4], 16) 20 """ @spec undigits([integer], integer) :: integer def undigits(digits, base \\ 10) when is_integer(base) do do_undigits(digits, base, 0) end defp do_undigits([], _base, acc), do: acc defp do_undigits([digit | tail], base, acc) do do_undigits(tail, base, acc * base + digit) end @doc """ Converts a binary from a text representation of an integer in an optional base `base` to the corresponding integer. If the base `base` is not given, base 10 will be used. If successful, returns a tuple of the form `{integer, remainder_of_binary}`. Otherwise `:error`. Raises an error if `base` is less than 2 or more than 36. ## Examples iex> Integer.parse("34") {34, ""} iex> Integer.parse("34.5") {34, ".5"} iex> Integer.parse("three") :error iex> Integer.parse("34", 10) {34, ""} iex> Integer.parse("f4", 16) {244, ""} iex> Integer.parse("Awww++", 36) {509216, "++"} iex> Integer.parse("fab", 10) :error iex> Integer.parse("a2", 38) ** (ArgumentError) invalid base 38 """ @spec parse(binary, 2..36) :: {integer, binary} | :error | no_return def parse(binary, base \\ 10) def parse(binary, base) when is_integer(base) and base in 2..36 do parse_in_base(binary, base) end def parse(_, base) do raise ArgumentError, "invalid base #{base}" end defp parse_in_base(<< ?-, bin :: binary >>, base) do case do_parse(bin, base) do :error -> :error {number, remainder} -> {-number, remainder} end end defp parse_in_base(<< ?+, bin :: binary >>, base) do do_parse(bin, base) end defp parse_in_base(bin, base) when is_binary(bin) do do_parse(bin, base) end defp do_parse(<< char, bin :: binary >>, base) do if valid_digit_in_base?(char, base) do do_parse(bin, base, parse_digit(char, base)) else :error end end defp do_parse(_, _), do: :error defp do_parse(<< char, rest :: binary >>, base, acc) do if valid_digit_in_base?(char, base) do do_parse(rest, base, base * acc + parse_digit(char, base)) else {acc, << char, rest :: binary >>} end end defp do_parse(bitstring, _, acc) do {acc, bitstring} end defp parse_digit(char, _) do cond do char in ?0..?9 -> char - ?0 char in ?A..?Z -> char - ?A + 10 true -> char - ?a + 10 end end defp valid_digit_in_base?(char, base) do if base <= 10 do char in ?0..(?0 + base - 1) else char in ?0..?9 or char in ?A..(?A + base - 11) or char in ?a..(?a + base - 11) end end @doc """ Returns a binary which corresponds to the text representation of `some_integer`. Inlined by the compiler. ## Examples iex> Integer.to_string(123) "123" """ @spec to_string(integer) :: String.t def to_string(some_integer) do :erlang.integer_to_binary(some_integer) end @doc """ Returns a binary which corresponds to the text representation of `some_integer` in base `base`. Inlined by the compiler. ## Examples iex> Integer.to_string(100, 16) "64" """ @spec to_string(integer, 2..36) :: String.t def to_string(some_integer, base) do :erlang.integer_to_binary(some_integer, base) end @doc """ Returns a char list which corresponds to the text representation of the given integer. Inlined by the compiler. ## Examples iex> Integer.to_char_list(7) '7' """ @spec to_char_list(integer) :: char_list def to_char_list(number) do :erlang.integer_to_list(number) end @doc """ Returns a char list which corresponds to the text representation of the given integer in the given base. Inlined by the compiler. ## Examples iex> Integer.to_char_list(1023, 16) '3FF' """ @spec to_char_list(integer, 2..36) :: char_list def to_char_list(number, base) do :erlang.integer_to_list(number, base) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io.ex000066400000000000000000000267631254730255300207100ustar00rootroot00000000000000defmodule IO do @moduledoc """ Functions handling IO. Many functions in this module expect an IO device as an argument. An IO device must be a pid or an atom representing a process. For convenience, Elixir provides `:stdio` and `:stderr` as shortcuts to Erlang's `:standard_io` and `:standard_error`. The majority of the functions expect char data, i.e. strings or lists of characters and strings. In case another type is given, it will do a conversion to string via the `String.Chars` protocol (as shown in typespecs). The functions starting with `bin*` expect iodata as an argument, i.e. binaries or lists of bytes and binaries. ## IO devices An IO device may be an atom or a pid. In case it is an atom, the atom must be the name of a registered process. However, there are three exceptions for this rule: * `:standard_io` - when the `:standard_io` atom is given, it is treated as a shortcut for `Process.group_leader` * `:stdio` - is a shortcut for `:standard_io` * `:stderr` - is a shortcut for `:standard_error` """ @type device :: atom | pid @type nodata :: {:error, term} | :eof @type chardata() :: :unicode.chardata() import :erlang, only: [group_leader: 0] defmacrop is_iodata(data) do quote do is_list(unquote(data)) or is_binary(unquote(data)) end end @doc """ Reads `count` characters from the IO device, a whole `:line` or the whole device with `:all`. It returns: * `data` - the input characters * `:eof` - end of file was encountered * `{:error, reason}` - other (rare) error condition; for instance, `{:error, :estale}` if reading from an NFS volume If `:all` is given, `:eof` is never returned, but an empty string in case the device has reached EOF. """ @spec read(device, :all | :line | non_neg_integer) :: chardata | nodata def read(device \\ group_leader, chars_or_line) def read(device, :all) do do_read_all(map_dev(device), "") end def read(device, :line) do :io.get_line(map_dev(device), '') end def read(device, count) when count >= 0 do :io.get_chars(map_dev(device), '', count) end defp do_read_all(mapped_dev, acc) do case :io.get_line(mapped_dev, "") do line when is_binary(line) -> do_read_all(mapped_dev, acc <> line) :eof -> acc other -> other end end @doc """ Reads `count` characters from the IO device, a whole `:line` or the whole device with `:all`. It returns: * `data` - the input characters * `:eof` - end of file was encountered * `{:error, reason}` - other (rare) error condition; for instance, `{:error, :estale}` if reading from an NFS volume If `:all` is given, `:eof` is never returned, but an empty string in case the device has reached EOF. Note: do not use this function on IO devices in unicode mode as it will return the wrong result. """ @spec binread(device, :all | :line | non_neg_integer) :: iodata | nodata def binread(device \\ group_leader, chars_or_line) def binread(device, :all) do do_binread_all(map_dev(device), "") end def binread(device, :line) do case :file.read_line(map_dev(device)) do {:ok, data} -> data other -> other end end def binread(device, count) when count >= 0 do case :file.read(map_dev(device), count) do {:ok, data} -> data other -> other end end @read_all_size 4096 defp do_binread_all(mapped_dev, acc) do case :file.read(mapped_dev, @read_all_size) do {:ok, data} -> do_binread_all(mapped_dev, acc <> data) :eof -> acc other -> other end end @doc """ Writes the given argument to the given device. By default the device is the standard output. It returns `:ok` if it succeeds. ## Examples IO.write "sample" #=> "sample" IO.write :stderr, "error" #=> "error" """ @spec write(device, chardata | String.Chars.t) :: :ok def write(device \\ group_leader(), item) do :io.put_chars map_dev(device), to_chardata(item) end @doc """ Writes the given argument to the given device as a binary, no unicode conversion happens. Check `write/2` for more information. Note: do not use this function on IO devices in unicode mode as it will return the wrong result. """ @spec binwrite(device, iodata) :: :ok | {:error, term} def binwrite(device \\ group_leader(), item) when is_iodata(item) do :file.write map_dev(device), item end @doc """ Writes the argument to the device, similar to `write/2`, but adds a newline at the end. The argument is expected to be a chardata. """ @spec puts(device, chardata | String.Chars.t) :: :ok def puts(device \\ group_leader(), item) do erl_dev = map_dev(device) :io.put_chars erl_dev, [to_chardata(item), ?\n] end @doc """ Inspects and writes the given argument to the device. It enables pretty printing by default with width of 80 characters. The width can be changed by explicitly passing the `:width` option. ## Examples IO.inspect Process.list, width: 40 """ @spec inspect(term, Keyword.t) :: term def inspect(item, opts \\ []) do inspect group_leader(), item, opts end @doc """ Inspects the item with options using the given device. """ @spec inspect(device, term, Keyword.t) :: term def inspect(device, item, opts) when is_list(opts) do opts = struct(Inspect.Opts, opts) iodata = Inspect.Algebra.format(Inspect.Algebra.to_doc(item, opts), opts.width) puts device, iodata item end @doc """ Gets a number of bytes from the io device. If the io device is a unicode device, `count` implies the number of unicode codepoints to be retrieved. Otherwise, `count` is the number of raw bytes to be retrieved. It returns: * `data` - the input characters * `:eof` - end of file was encountered * `{:error, reason}` - other (rare) error condition; for instance, `{:error, :estale}` if reading from an NFS volume """ @spec getn(chardata | String.Chars.t, pos_integer) :: chardata | nodata @spec getn(device, chardata | String.Chars.t) :: chardata | nodata def getn(prompt, count \\ 1) def getn(prompt, count) when is_integer(count) do getn(group_leader, prompt, count) end def getn(device, prompt) do getn(device, prompt, 1) end @doc """ Gets a number of bytes from the io device. If the io device is a unicode device, `count` implies the number of unicode codepoints to be retrieved. Otherwise, `count` is the number of raw bytes to be retrieved. """ @spec getn(device, chardata | String.Chars.t, pos_integer) :: chardata | nodata def getn(device, prompt, count) do :io.get_chars(map_dev(device), to_chardata(prompt), count) end @doc """ Reads a line from the IO device. It returns: * `data` - the characters in the line terminated by a LF (or end of file) * `:eof` - end of file was encountered * `{:error, reason}` - other (rare) error condition; for instance, `{:error, :estale}` if reading from an NFS volume """ @spec gets(device, chardata | String.Chars.t) :: chardata | nodata def gets(device \\ group_leader(), prompt) do :io.get_line(map_dev(device), to_chardata(prompt)) end @doc """ Converts the io device into a `IO.Stream`. An `IO.Stream` implements both `Enumerable` and `Collectable`, allowing it to be used for both read and write. The device is iterated line by line if `:line` is given or by a given number of codepoints. This reads the IO as utf-8. Check out `IO.binstream/2` to handle the IO as a raw binary. Note that an IO stream has side effects and every time you go over the stream you may get different results. ## Examples Here is an example on how we mimic an echo server from the command line: Enum.each IO.stream(:stdio, :line), &IO.write(&1) """ @spec stream(device, :line | pos_integer) :: Enumerable.t def stream(device, line_or_codepoints) do IO.Stream.__build__(map_dev(device), false, line_or_codepoints) end @doc """ Converts the IO device into a `IO.Stream`. An `IO.Stream` implements both `Enumerable` and `Collectable`, allowing it to be used for both read and write. The device is iterated line by line or by a number of bytes. This reads the IO device as a raw binary. Note that an IO stream has side effects and every time you go over the stream you may get different results. Finally, do not use this function on IO devices in unicode mode as it will return the wrong result. """ @spec binstream(device, :line | pos_integer) :: Enumerable.t def binstream(device, line_or_bytes) do IO.Stream.__build__(map_dev(device), true, line_or_bytes) end @doc """ Converts chardata (a list of integers representing codepoints, lists and strings) into a string. In case the conversion fails, it raises a `UnicodeConversionError`. If a string is given, returns the string itself. ## Examples iex> IO.chardata_to_string([0x00E6, 0x00DF]) "æß" iex> IO.chardata_to_string([0x0061, "bc"]) "abc" """ @spec chardata_to_string(chardata) :: String.t | no_return def chardata_to_string(string) when is_binary(string) do string end def chardata_to_string(list) when is_list(list) do case :unicode.characters_to_binary(list) do result when is_binary(result) -> result {:error, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :invalid {:incomplete, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :incomplete end end @doc """ Converts iodata (a list of integers representing bytes, lists and binaries) into a binary. Notice that this function treats lists of integers as raw bytes and does not perform any kind of encoding conversion. If you want to convert from a char list to a string (UTF-8 encoded), please use `chardata_to_string/1` instead. If this function receives a binary, the same binary is returned. Inlined by the compiler. ## Examples iex> bin1 = <<1, 2, 3>> iex> bin2 = <<4, 5>> iex> bin3 = <<6>> iex> IO.iodata_to_binary([bin1, 1, [2, 3, bin2], 4|bin3]) <<1, 2, 3, 1, 2, 3, 4, 5, 4, 6>> iex> bin = <<1, 2, 3>> iex> IO.iodata_to_binary(bin) <<1, 2, 3>> """ @spec iodata_to_binary(iodata) :: binary def iodata_to_binary(item) do :erlang.iolist_to_binary(item) end @doc """ Returns the size of an iodata. Inlined by the compiler. ## Examples iex> IO.iodata_length([1, 2|<<3, 4>>]) 4 """ @spec iodata_length(iodata) :: non_neg_integer def iodata_length(item) do :erlang.iolist_size(item) end @doc false def each_stream(device, what) do case read(device, what) do :eof -> {:halt, device} {:error, reason} -> raise IO.StreamError, reason: reason data -> {[data], device} end end @doc false def each_binstream(device, what) do case binread(device, what) do :eof -> {:halt, device} {:error, reason} -> raise IO.StreamError, reason: reason data -> {[data], device} end end @compile {:inline, map_dev: 1, to_chardata: 1} # Map the Elixir names for standard io and error to Erlang names defp map_dev(:stdio), do: :standard_io defp map_dev(:stderr), do: :standard_error defp map_dev(other) when is_atom(other) or is_pid(other) or is_tuple(other), do: other defp to_chardata(list) when is_list(list), do: list defp to_chardata(other), do: to_string(other) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io/000077500000000000000000000000001254730255300203345ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io/ansi.ex000066400000000000000000000133221254730255300216250ustar00rootroot00000000000000defmodule IO.ANSI.Sequence do @moduledoc false defmacro defsequence(name, code, terminator \\ "m") do quote bind_quoted: [name: name, code: code, terminator: terminator] do def unquote(name)() do "\e[#{unquote(code)}#{unquote(terminator)}" end defp format_sequence(unquote(name)) do unquote(name)() end end end end defmodule IO.ANSI do @moduledoc """ Functionality to render ANSI escape sequences (http://en.wikipedia.org/wiki/ANSI_escape_code) — characters embedded in text used to control formatting, color, and other output options on video text terminals. """ import IO.ANSI.Sequence @typep ansicode :: atom() @typep ansilist :: maybe_improper_list(char() | ansicode() | binary() | ansilist(), binary() | ansicode() | []) @type ansidata :: ansilist() | ansicode() | binary() @doc """ Checks if ANSI coloring is supported and enabled on this machine. This function simply reads the configuration value for `:ansi_enabled` in the `:elixir` application. The value is by default `false` unless Elixir can detect during startup that both `stdout` and `stderr` are terminals. """ @spec enabled? :: boolean def enabled? do Application.get_env(:elixir, :ansi_enabled, false) end @doc "Resets all attributes" defsequence :reset, 0 @doc "Bright (increased intensity) or Bold" defsequence :bright, 1 @doc "Faint (decreased intensity), not widely supported" defsequence :faint, 2 @doc "Italic: on. Not widely supported. Sometimes treated as inverse." defsequence :italic, 3 @doc "Underline: Single" defsequence :underline, 4 @doc "Blink: Slow. Less than 150 per minute" defsequence :blink_slow, 5 @doc "Blink: Rapid. MS-DOS ANSI.SYS; 150 per minute or more; not widely supported" defsequence :blink_rapid, 6 @doc "Image: Negative. Swap foreground and background" defsequence :inverse, 7 @doc "Image: Negative. Swap foreground and background" defsequence :reverse, 7 @doc "Conceal. Not widely supported" defsequence :conceal, 8 @doc "Crossed-out. Characters legible, but marked for deletion. Not widely supported." defsequence :crossed_out, 9 @doc "Sets primary (default) font" defsequence :primary_font, 10 for font_n <- [1, 2, 3, 4, 5, 6, 7, 8, 9] do @doc "Sets alternative font #{font_n}" defsequence :"font_#{font_n}", font_n + 10 end @doc "Normal color or intensity" defsequence :normal, 22 @doc "Not italic" defsequence :not_italic, 23 @doc "Underline: None" defsequence :no_underline, 24 @doc "Blink: off" defsequence :blink_off, 25 colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white] for {color, code} <- Enum.with_index(colors) do @doc "Sets foreground color to #{color}" defsequence color, code + 30 @doc "Sets background color to #{color}" defsequence :"#{color}_background", code + 40 end @doc "Default text color" defsequence :default_color, 39 @doc "Default background color" defsequence :default_background, 49 @doc "Framed" defsequence :framed, 51 @doc "Encircled" defsequence :encircled, 52 @doc "Overlined" defsequence :overlined, 53 @doc "Not framed or encircled" defsequence :not_framed_encircled, 54 @doc "Not overlined" defsequence :not_overlined, 55 @doc "Send cursor home" defsequence :home, "", "H" @doc "Clear screen" defsequence :clear, "2", "J" defp format_sequence(other) do raise ArgumentError, "invalid ANSI sequence specification: #{other}" end @doc ~S""" Formats a chardata-like argument by converting named ANSI sequences into actual ANSI codes. The named sequences are represented by atoms. It will also append an `IO.ANSI.reset` to the chardata when a conversion is performed. If you don't want this behaviour, use `format_fragment/2`. An optional boolean parameter can be passed to enable or disable emitting actual ANSI codes. When `false`, no ANSI codes will emitted. By default checks if ANSI is enabled using the `enabled?/0` function. ## Examples iex> IO.ANSI.format(["Hello, ", :red, :bright, "world!"], true) [[[[[[], "Hello, "] | "\e[31m"] | "\e[1m"], "world!"] | "\e[0m"] """ def format(chardata, emit \\ enabled?) when is_boolean(emit) do do_format(chardata, [], [], emit, :maybe) end @doc ~S""" Formats a chardata-like argument by converting named ANSI sequences into actual ANSI codes. The named sequences are represented by atoms. An optional boolean parameter can be passed to enable or disable emitting actual ANSI codes. When `false`, no ANSI codes will emitted. By default checks if ANSI is enabled using the `enabled?/0` function. ## Examples iex> IO.ANSI.format_fragment([:bright, 'Word'], true) [[[[[[] | "\e[1m"], 87], 111], 114], 100] """ def format_fragment(chardata, emit \\ enabled?) when is_boolean(emit) do do_format(chardata, [], [], emit, false) end defp do_format([term | rest], rem, acc, emit, append_reset) do do_format(term, [rest | rem], acc, emit, append_reset) end defp do_format(term, rem, acc, true, append_reset) when is_atom(term) do do_format([], rem, [acc | format_sequence(term)], true, !!append_reset) end defp do_format(term, rem, acc, false, append_reset) when is_atom(term) do do_format([], rem, acc, false, append_reset) end defp do_format(term, rem, acc, emit, append_reset) when not is_list(term) do do_format([], rem, [acc | [term]], emit, append_reset) end defp do_format([], [next | rest], acc, emit, append_reset) do do_format(next, rest, acc, emit, append_reset) end defp do_format([], [], acc, true, true) do [acc | IO.ANSI.reset] end defp do_format([], [], acc, _emit, _append_reset) do acc end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io/ansi/000077500000000000000000000000001254730255300212665ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io/ansi/docs.ex000066400000000000000000000406651254730255300225670ustar00rootroot00000000000000defmodule IO.ANSI.Docs do @moduledoc false @bullets [?*, ?-, ?+] @doc """ The default options used by this module. The supported values are: * `:enabled` - toggles coloring on and off (true) * `:doc_bold` - bold text (bright) * `:doc_code` - code blocks (cyan, bright) * `:doc_headings` - h1 and h2 headings (yellow, bright) * `:doc_inline_code` - inline code (cyan) * `:doc_table_heading` - style for table headings * `:doc_title` - top level heading (reverse, yellow, bright) * `:doc_underline` - underlined text (underline) * `:width` - the width to format the text (80) Values for the color settings are strings with comma-separated ANSI values. """ def default_options do [enabled: true, doc_bold: [:bright], doc_code: [:cyan, :bright], doc_headings: [:yellow], doc_inline_code: [:cyan], doc_table_heading: [:reverse], doc_title: [:reverse, :yellow], doc_underline: [:underline], width: 80] end @doc """ Prints the head of the documentation (i.e. the function signature). See `default_options/0` for docs on the supported options. """ def print_heading(heading, options \\ []) do IO.puts IO.ANSI.reset options = Keyword.merge(default_options, options) width = options[:width] padding = div(width + String.length(heading), 2) heading = heading |> String.rjust(padding) |> String.ljust(width) write(:doc_title, heading, options) newline_after_block end @doc """ Prints the documentation body. In addition to the printing string, takes a set of options defined in `default_options/1`. """ def print(doc, options \\ []) do options = Keyword.merge(default_options, options) doc |> String.split(["\r\n", "\n"], trim: false) |> Enum.map(&String.rstrip/1) |> process([], "", options) end defp process([], text, indent, options) do write_text(text, indent, options) end defp process(["# " <> heading | rest], text, indent, options) do write_text(text, indent, options) write_h1(String.strip(heading), options) process(rest, [], "", options) end defp process(["## " <> heading | rest], text, indent, options) do write_text(text, indent, options) write_h2(String.strip(heading), options) process(rest, [], "", options) end defp process(["### " <> heading | rest], text, indent, options) do write_text(text, indent, options) write_h3(String.strip(heading), indent, options) process(rest, [], "", options) end defp process(["" | rest], text, indent, options) do write_text(text, indent, options) process(rest, [], indent, options) end defp process([" " <> line | rest], text, indent, options) do write_text(text, indent, options) process_code(rest, [line], indent, options) end defp process(["```" <> _line | rest], text, indent, options) do process_fenced_code_block(rest, text, indent, options, _delimiter = "```") end defp process(["~~~" <> _line | rest], text, indent, options) do process_fenced_code_block(rest, text, indent, options, _delimiter = "~~~") end defp process(all=[line | rest], text, indent, options) do {stripped, count} = strip_spaces(line, 0, :infinity) if is_table_line?(stripped) and rest != [] and is_table_line?(hd(rest)) do write_text(text, indent, options) process_table(all, indent, options) else case stripped do <> when bullet in @bullets -> write_text(text, indent, options) process_list("• ", item, rest, count, indent, options) <> when d1 in ?0..?9 -> write_text(text, indent, options) process_list(<>, item, rest, count, indent, options) <> when d1 in ?0..?9 and d2 in ?0..?9 -> write_text(text, indent, options) process_list(<>, item, rest, count, indent, options) _ -> process(rest, [stripped | text], indent, options) end end end ## Headings defp write_h1(heading, options) do write_h2(String.upcase(heading), options) end defp write_h2(heading, options) do write(:doc_headings, heading, options) newline_after_block end defp write_h3(heading, indent, options) do IO.write(indent) write(:doc_headings, heading, options) newline_after_block end ## Lists defp process_list(entry, line, rest, count, indent, options) do # The first list always win some extra padding if indent == "", do: entry = " " <> entry new_indent = indent <> String.duplicate(" ", String.length(entry)) {contents, rest, done} = process_list_next(rest, count, byte_size(new_indent), []) process(contents, [indent <> entry <> line, :no_wrap], new_indent, options) if done, do: newline_after_block() process(rest, [], indent, options) end defp process_list_next([line | rest], count, max, acc) do {stripped, next_count} = strip_spaces(line, 0, max) case process_list_next_kind(stripped, rest, count, next_count) do :next -> process_list_next(rest, count, max, [stripped | acc]) :done -> {Enum.reverse(acc), [line | rest], true} :list -> {Enum.reverse(acc), [line | rest], false} end end defp process_list_next([], _count, _max, acc) do {Enum.reverse(acc), [], true} end defp process_list_next_kind(stripped, rest, count, next_count) do case {stripped, rest} do {<>, _} when bullet in @bullets and next_count <= count -> :list {<>, _} when d1 in ?0..?9 and next_count <= count -> :list {<>, _} when d1 in ?0..?9 and d2 in ?0..?9 and next_count <= count -> :list {"", [" " <> _ | _]} -> :next {"", _} -> :done _ -> :next end end ## Text defp write_text(text, indent, options) do case Enum.reverse(text) do [:no_wrap|rest] -> write_text(rest, indent, options, true) rest -> write_text(rest, indent, options, false) end end defp write_text([], _indent, _options, _no_wrap) do :ok end defp write_text(lines, indent, options, no_wrap) do lines |> Enum.join(" ") |> handle_links |> handle_inline(options) |> String.split(~r{\s}) |> write_with_wrap(options[:width] - byte_size(indent), indent, no_wrap) unless no_wrap, do: newline_after_block() end ## Code blocks defp process_code([], code, indent, options) do write_code(code, indent, options) end # Blank line between code blocks defp process_code(["", " " <> line | rest], code, indent, options) do process_code(rest, [line, "" | code], indent, options) end defp process_code([" " <> line | rest], code, indent, options) do process_code(rest, [line|code], indent, options) end defp process_code(rest, code, indent, options) do write_code(code, indent, options) process(rest, [], indent, options) end defp process_fenced_code_block(rest, text, indent, options, delimiter) do write_text(text, indent, options) process_fenced_code(rest, [], indent, options, delimiter) end defp process_fenced_code([], code, indent, options, _delimiter) do write_code(code, indent, options) end defp process_fenced_code([line | rest], code, indent, options, delimiter) do if line === delimiter do process_code(rest, code, indent, options) else process_fenced_code(rest, [line|code], indent, options, delimiter) end end defp write_code(code, indent, options) do write(:doc_code, "#{indent}┃ #{Enum.join(Enum.reverse(code), "\n#{indent}┃ ")}", options) newline_after_block end ## Tables defp process_table(lines, indent, options) do {table, rest} = Enum.split_while(lines, &is_table_line?/1) table_lines(table, options) newline_after_block process(rest, [], indent, options) end defp table_lines(lines, options) do lines = Enum.map(lines, &split_into_columns(&1, options)) count = Enum.map(lines, &length/1) |> Enum.max lines = Enum.map(lines, &pad_to_number_of_columns(&1, count)) widths = for line <- lines, do: (for {_col, length} <- line, do: length) col_widths = Enum.reduce(widths, List.duplicate(0, count), &max_column_widths/2) render_table(lines, col_widths, options) end defp split_into_columns(line, options) do line |> String.strip(?|) |> String.strip() |> String.split(~r/\s\|\s/) |> Enum.map(&render_column(&1, options)) end defp render_column(col, options) do col = col |> String.replace(~r/\\ \|/x, "|") |> handle_links |> handle_inline(options) {col, length_without_escape(col, 0)} end defp pad_to_number_of_columns(cols, col_count), do: cols ++ List.duplicate({"", 0}, col_count - length(cols)) defp max_column_widths(cols, widths), do: Enum.zip(cols, widths) |> Enum.map(fn {a, b} -> max(a, b) end) # If second line is heading separator, use the heading style on the first defp render_table([first, second | rest], widths, options) do combined = Enum.zip(first, widths) if table_header?(second) do draw_table_row(combined, options, :heading) render_table(rest, widths, options) else draw_table_row(combined, options) render_table([second | rest], widths, options) end end defp render_table([first | rest], widths, options) do combined = Enum.zip(first, widths) draw_table_row(combined, options) render_table(rest, widths, options) end defp render_table([], _, _), do: nil defp table_header?(row), do: Enum.all?(row, fn {col, _} -> col =~ ~r/^:?-+:?$/ end) defp draw_table_row(cols_and_widths, options, heading \\ false) do columns = Enum.map_join(cols_and_widths, " | ", fn {{col, length}, width} -> col <> String.duplicate(" ", width - length) end) if heading do write(:doc_table_heading, columns, options) else IO.puts columns end end defp is_table_line?(line) do Regex.match?(~r''' ( ^ \s{0,3} \| (?: [^|]+ \|)+ \s* $ ) | (\s \| \s) '''x, line) end ## Helpers defp strip_spaces(" " <> line, acc, max) when acc < max, do: strip_spaces(line, acc + 1, max) defp strip_spaces(rest, acc, _max), do: {rest, acc} defp write(style, string, options) do IO.puts [color(style, options), string, IO.ANSI.reset] end defp write_with_wrap([], _available, _indent, _first) do :ok end defp write_with_wrap(words, available, indent, first) do {words, rest} = take_words(words, available, []) IO.puts (if first, do: "", else: indent) <> Enum.join(words, " ") write_with_wrap(rest, available, indent, false) end defp take_words([word|words], available, acc) do available = available - length_without_escape(word, 0) cond do # It fits, take one for space and continue decreasing available > 0 -> take_words(words, available - 1, [word|acc]) # No space but we got no words acc == [] -> {[word], words} # Otherwise true -> {Enum.reverse(acc), [word|words]} end end defp take_words([], _available, acc) do {Enum.reverse(acc), []} end defp length_without_escape(<< ?\e, ?[, _, _, ?m, rest :: binary >>, count) do length_without_escape(rest, count) end defp length_without_escape(<< ?\e, ?[, _, ?m, rest :: binary >>, count) do length_without_escape(rest, count) end defp length_without_escape(rest, count) do case String.next_grapheme(rest) do {_, rest} -> length_without_escape(rest, count + 1) nil -> count end end defp handle_links(text) do text |> remove_square_brackets_in_link |> escape_underlines_in_link end defp escape_underlines_in_link(text) do case Regex.match?(~r{.*(https?\S*)}, text) do true -> Regex.replace(~r{_}, text, "\\\\_") _ -> text end end defp remove_square_brackets_in_link(text) do Regex.replace(~r{\[(.*?)\]\((.*?)\)}, text, "\\1 (\\2)") end # We have four entries: **, *, _ and `. # # The first three behave the same while the last one is simpler # when it comes to delimiters. But, since the first has two # characters, we need to handle 3 cases: # # 1. ** # 2. _ and * # 3. ` # # Where the first two should have the same code but match differently. @single [?_, ?*] # Characters that can mark the beginning or the end of a word. # Only support the most common ones at this moment. @delimiters [?\s, ?', ?", ?!, ?@, ?#, ?$, ?%, ?^, ?&, ?-, ?+, ?(, ?), ?[, ?], ?{, ?}, ?<, ?>, ?.] # Inline start defp handle_inline(<>, options) do handle_inline(rest, ?d, ["**"], [], options) end defp handle_inline(<>, options) when mark in @single do handle_inline(rest, mark, [<>], [], options) end defp handle_inline(rest, options) do handle_inline(rest, nil, [], [], options) end # Inline delimiters defp handle_inline(<>, nil, buffer, acc, options) when rest != "" and delimiter in @delimiters do handle_inline(rest, ?d, ["**"], [delimiter, Enum.reverse(buffer)|acc], options) end defp handle_inline(<>, nil, buffer, acc, options) when rest != "" and delimiter in @delimiters and mark in @single do handle_inline(rest, mark, [<>], [delimiter, Enum.reverse(buffer)|acc], options) end defp handle_inline(<>, nil, buffer, acc, options) when rest != "" do handle_inline(rest, ?`, ["`"], [Enum.reverse(buffer)|acc], options) end # Clauses for handling escape defp handle_inline(<>, nil, buffer, acc, options) when rest != "" do handle_inline(rest, ?d, ["**"], [?\\, Enum.reverse(buffer)|acc], options) end defp handle_inline(<>, nil, buffer, acc, options) when rest != "" and mark in @single do handle_inline(rest, mark, [<>], [?\\, Enum.reverse(buffer)|acc], options) end defp handle_inline(<>, limit, buffer, acc, options) do handle_inline(rest, limit, [?\\|buffer], acc, options) end # An escape is not valid inside ` defp handle_inline(<>, limit, buffer, acc, options) when not(mark == limit and mark == ?`) do handle_inline(rest, limit, [mark|buffer], acc, options) end # Inline end defp handle_inline(<>, ?d, buffer, acc, options) when delimiter in @delimiters do handle_inline(<>, nil, [], [inline_buffer(buffer, options)|acc], options) end defp handle_inline(<>, mark, buffer, acc, options) when delimiter in @delimiters and mark in @single do handle_inline(<>, nil, [], [inline_buffer(buffer, options)|acc], options) end defp handle_inline(<>, ?d, buffer, acc, options) when rest == "" do handle_inline(<<>>, nil, [], [inline_buffer(buffer, options)|acc], options) end defp handle_inline(<>, mark, buffer, acc, options) when rest == "" and mark in @single do handle_inline(<<>>, nil, [], [inline_buffer(buffer, options)|acc], options) end defp handle_inline(<>, ?`, buffer, acc, options) do handle_inline(rest, nil, [], [inline_buffer(buffer, options)|acc], options) end # Catch all defp handle_inline(<>, mark, buffer, acc, options) do handle_inline(rest, mark, [char|buffer], acc, options) end defp handle_inline(<<>>, _mark, buffer, acc, _options) do IO.iodata_to_binary Enum.reverse([Enum.reverse(buffer)|acc]) end defp inline_buffer(buffer, options) do [h|t] = Enum.reverse([IO.ANSI.reset|buffer]) [color_for(h, options)|t] end defp color_for(mark, colors) do case mark do "`" -> color(:doc_inline_code, colors) "_" -> color(:doc_underline, colors) "*" -> color(:doc_bold, colors) "**" -> color(:doc_bold, colors) end end defp color(style, colors) do color = colors[style] IO.ANSI.format_fragment(color, colors[:enabled]) end defp newline_after_block, do: IO.puts(IO.ANSI.reset) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/io/stream.ex000066400000000000000000000032741254730255300221730ustar00rootroot00000000000000defmodule IO.StreamError do defexception [:reason, :message] def exception(opts) do reason = opts[:reason] formatted = IO.iodata_to_binary(:file.format_error(reason)) %IO.StreamError{message: "error during streaming: #{formatted}", reason: reason} end end defmodule IO.Stream do @moduledoc """ Defines a `IO.Stream` struct returned by `IO.stream/2` and `IO.binstream/2`. The following fields are public: * `device` - the IO device * `raw` - a boolean indicating if bin functions should be used * `line_or_bytes` - if reading should read lines or a given amount of bytes """ defstruct device: nil, raw: true, line_or_bytes: :line @type t :: %__MODULE__{} @doc false def __build__(device, raw, line_or_bytes) do %IO.Stream{device: device, raw: raw, line_or_bytes: line_or_bytes} end defimpl Collectable do def into(%{device: device, raw: raw} = stream) do {:ok, into(stream, device, raw)} end defp into(stream, device, raw) do fn :ok, {:cont, x} -> case raw do true -> IO.binwrite(device, x) false -> IO.write(device, x) end :ok, _ -> stream end end end defimpl Enumerable do def reduce(%{device: device, raw: raw, line_or_bytes: line_or_bytes}, acc, fun) do next_fun = case raw do true -> &IO.each_binstream(&1, line_or_bytes) false -> &IO.each_stream(&1, line_or_bytes) end Stream.resource(fn -> device end, next_fun, &(&1)).(acc, fun) end def count(_stream) do {:error, __MODULE__} end def member?(_stream, _term) do {:error, __MODULE__} end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel.ex000066400000000000000000002740251254730255300215550ustar00rootroot00000000000000# Use elixir_bootstrap module to be able to bootstrap Kernel. # The bootstrap module provides simpler implementations of the # functions removed, simple enough to bootstrap. import Kernel, except: [@: 1, defmodule: 2, def: 1, def: 2, defp: 2, defmacro: 1, defmacro: 2, defmacrop: 2] import :elixir_bootstrap defmodule Kernel do @moduledoc """ `Kernel` provides the default macros and functions Elixir imports into your environment. These macros and functions can be skipped or cherry-picked via the `import` macro. For instance, if you want to tell Elixir not to import the `if` macro, you can do: import Kernel, except: [if: 2] Elixir also has special forms that are always imported and cannot be skipped. These are described in `Kernel.SpecialForms`. Some of the functions described in this module are inlined by the Elixir compiler into their Erlang counterparts in the `:erlang` module. Those functions are called BIFs (builtin internal functions) in Erlang-land and they exhibit interesting properties, as some of them are allowed in guards and others are used for compiler optimizations. Most of the inlined functions can be seen in effect when capturing the function: iex> &Kernel.is_atom/1 &:erlang.is_atom/1 Those functions will be explicitly marked in their docs as "inlined by the compiler". """ ## Delegations to Erlang with inlining (macros) @doc """ Returns an integer or float which is the arithmetical absolute value of `number`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> abs(-3.33) 3.33 iex> abs(-3) 3 """ @spec abs(number) :: number def abs(number) do :erlang.abs(number) end @doc """ Invokes the given `fun` with the array of arguments `args`. Inlined by the compiler. ## Examples iex> apply(fn x -> x * 2 end, [2]) 4 """ @spec apply(fun, [any]) :: any def apply(fun, args) do :erlang.apply(fun, args) end @doc """ Invokes the given `fun` from `module` with the array of arguments `args`. Inlined by the compiler. ## Examples iex> apply(Enum, :reverse, [[1, 2, 3]]) [3, 2, 1] """ @spec apply(module, atom, [any]) :: any def apply(module, fun, args) do :erlang.apply(module, fun, args) end @doc """ Extracts the part of the binary starting at `start` with length `length`. Binaries are zero-indexed. If `start` or `length` reference in any way outside the binary, an `ArgumentError` exception is raised. Allowed in guard tests. Inlined by the compiler. ## Examples iex> binary_part("foo", 1, 2) "oo" A negative `length` can be used to extract bytes that come *before* the byte at `start`: iex> binary_part("Hello", 5, -3) "llo" """ @spec binary_part(binary, pos_integer, integer) :: binary def binary_part(binary, start, length) do :erlang.binary_part(binary, start, length) end @doc """ Returns an integer which is the size in bits of `bitstring`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> bit_size(<<433::16, 3::3>>) 19 iex> bit_size(<<1, 2, 3>>) 24 """ @spec bit_size(bitstring) :: non_neg_integer def bit_size(bitstring) do :erlang.bit_size(bitstring) end @doc """ Returns the number of bytes needed to contain `bitstring`. That is, if the number of bits in `bitstring` is not divisible by 8, the resulting number of bytes will be rounded up (by excess). This operation happens in constant time. Allowed in guard tests. Inlined by the compiler. ## Examples iex> byte_size(<<433::16, 3::3>>) 3 iex> byte_size(<<1, 2, 3>>) 3 """ @spec byte_size(binary) :: non_neg_integer def byte_size(binary) do :erlang.byte_size(binary) end @doc """ Performs an integer division. Raises an `ArithmeticError` exception if one of the arguments is not an integer. Allowed in guard tests. Inlined by the compiler. ## Examples iex> div(5, 2) 2 """ @spec div(integer, integer) :: integer def div(left, right) do :erlang.div(left, right) end @doc """ Stops the execution of the calling process with the given reason. Since evaluating this function causes the process to terminate, it has no return value. Inlined by the compiler. ## Examples When a process reaches its end, by default it exits with reason `:normal`. You can also call `exit/1` explicitly if you want to terminate a process but not signal any failure: exit(:normal) In case something goes wrong, you can also use `exit/1` with a different reason: exit(:seems_bad) If the exit reason is not `:normal`, all the processes linked to the process that exited will crash (unless they are trapping exits). ## OTP exits Exits are used by the OTP to determine if a process exited abnormally or not. The following exits are considered "normal": * `exit(:normal)` * `exit(:shutdown)` * `exit({:shutdown, term})` Exiting with any other reason is considered abnormal and treated as a crash. This means the default supervisor behaviour kicks in, error reports are emitted, etc. This behaviour is relied on in many different places. For example, `ExUnit` uses `exit(:shutdown)` when exiting the test process to signal linked processes, supervision trees and so on to politely shutdown too. ## CLI exits Building on top of the exit signals mentioned above, if the process started by the command line exits with any of the three reasons above, its exit is considered normal and the Operating System process will exit with status 0. It is, however, possible to customize the Operating System exit signal by invoking: exit({:shutdown, integer}) This will cause the OS process to exit with the status given by `integer` while signaling all linked OTP processes to politely shutdown. Any other exit reason will cause the OS process to exit with status `1` and linked OTP processes to crash. """ @spec exit(term) :: no_return def exit(reason) do :erlang.exit(reason) end @doc """ Returns the head of a list; raises `ArgumentError` if the list is empty. Inlined by the compiler. ## Examples iex> hd([1, 2, 3, 4]) 1 """ @spec hd(list) :: term def hd(list) do :erlang.hd(list) end @doc """ Returns `true` if `term` is an atom; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_atom(term) :: boolean def is_atom(term) do :erlang.is_atom(term) end @doc """ Returns `true` if `term` is a binary; otherwise returns `false`. A binary always contains a complete number of bytes. Allowed in guard tests. Inlined by the compiler. ## Examples iex> is_binary "foo" true iex> is_binary <<1::3>> false """ @spec is_binary(term) :: boolean def is_binary(term) do :erlang.is_binary(term) end @doc """ Returns `true` if `term` is a bitstring (including a binary); otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> is_bitstring "foo" true iex> is_bitstring <<1::3>> true """ @spec is_bitstring(term) :: boolean def is_bitstring(term) do :erlang.is_bitstring(term) end @doc """ Returns `true` if `term` is either the atom `true` or the atom `false` (i.e., a boolean); otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_boolean(term) :: boolean def is_boolean(term) do :erlang.is_boolean(term) end @doc """ Returns `true` if `term` is a floating point number; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_float(term) :: boolean def is_float(term) do :erlang.is_float(term) end @doc """ Returns `true` if `term` is a function; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_function(term) :: boolean def is_function(term) do :erlang.is_function(term) end @doc """ Returns `true` if `term` is a function that can be applied with `arity` number of arguments; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> is_function(fn(x) -> x * 2 end, 1) true iex> is_function(fn(x) -> x * 2 end, 2) false """ @spec is_function(term, non_neg_integer) :: boolean def is_function(term, arity) do :erlang.is_function(term, arity) end @doc """ Returns `true` if `term` is an integer; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_integer(term) :: boolean def is_integer(term) do :erlang.is_integer(term) end @doc """ Returns `true` if `term` is a list with zero or more elements; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_list(term) :: boolean def is_list(term) do :erlang.is_list(term) end @doc """ Returns `true` if `term` is either an integer or a floating point number; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_number(term) :: boolean def is_number(term) do :erlang.is_number(term) end @doc """ Returns `true` if `term` is a pid (process identifier); otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_pid(term) :: boolean def is_pid(term) do :erlang.is_pid(term) end @doc """ Returns `true` if `term` is a port identifier; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_port(term) :: boolean def is_port(term) do :erlang.is_port(term) end @doc """ Returns `true` if `term` is a reference; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_reference(term) :: boolean def is_reference(term) do :erlang.is_reference(term) end @doc """ Returns `true` if `term` is a tuple; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_tuple(term) :: boolean def is_tuple(term) do :erlang.is_tuple(term) end @doc """ Returns `true` if `term` is a map; otherwise returns `false`. Allowed in guard tests. Inlined by the compiler. """ @spec is_map(term) :: boolean def is_map(term) do :erlang.is_map(term) end @doc """ Returns the length of `list`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> length([1, 2, 3, 4, 5, 6, 7, 8, 9]) 9 """ @spec length(list) :: non_neg_integer def length(list) do :erlang.length(list) end @doc """ Returns an almost unique reference. The returned reference will re-occur after approximately 2^82 calls; therefore it is unique enough for practical purposes. Inlined by the compiler. ## Examples make_ref() #=> #Reference<0.0.0.135> """ @spec make_ref() :: reference def make_ref() do :erlang.make_ref() end @doc """ Returns the size of a map. The size of a map is the number of key-value pairs that the map contains. This operation happens in constant time. Allowed in guard tests. Inlined by the compiler. ## Examples iex> map_size(%{a: "foo", b: "bar"}) 2 """ @spec map_size(map) :: non_neg_integer def map_size(map) do :erlang.map_size(map) end @doc """ Returns the biggest of the two given terms according to Erlang's term ordering. If the terms compare equal, the first one is returned. Inlined by the compiler. ## Examples iex> max(1, 2) 2 iex> max(:a, :b) :b """ @spec max(term, term) :: term def max(first, second) do :erlang.max(first, second) end @doc """ Returns the smallest of the two given terms according to Erlang's term ordering. If the terms compare equal, the first one is returned. Inlined by the compiler. ## Examples iex> min(1, 2) 1 iex> min("foo", "bar") "bar" """ @spec min(term, term) :: term def min(first, second) do :erlang.min(first, second) end @doc """ Returns an atom representing the name of the local node. If the node is not alive, `:nonode@nohost` is returned instead. Allowed in guard tests. Inlined by the compiler. """ @spec node() :: node def node do :erlang.node end @doc """ Returns the node where the given argument is located. The argument can be a pid, a reference, or a port. If the local node is not alive, `:nonode@nohost` is returned. Allowed in guard tests. Inlined by the compiler. """ @spec node(pid | reference | port) :: node def node(arg) do :erlang.node(arg) end @doc """ Computes the remainder of an integer division. Raises an `ArithmeticError` exception if one of the arguments is not an integer. Allowed in guard tests. Inlined by the compiler. ## Examples iex> rem(5, 2) 1 """ @spec rem(integer, integer) :: integer def rem(left, right) do :erlang.rem(left, right) end @doc """ Rounds a number to the nearest integer. Allowed in guard tests. Inlined by the compiler. ## Examples iex> round(5.6) 6 iex> round(5.2) 5 iex> round(-9.9) -10 """ @spec round(number) :: integer def round(number) do :erlang.round(number) end @doc """ Sends a message to the given `dest` and returns the message. `dest` may be a remote or local pid, a (local) port, a locally registered name, or a tuple `{registered_name, node}` for a registered name at another node. Inlined by the compiler. ## Examples iex> send self(), :hello :hello """ @spec send(dest :: pid | port | atom | {atom, node}, msg) :: msg when msg: any def send(dest, msg) do :erlang.send(dest, msg) end @doc """ Returns the pid (process identifier) of the calling process. Allowed in guard clauses. Inlined by the compiler. """ @spec self() :: pid def self() do :erlang.self() end @doc """ Spawns the given function and returns its pid. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples current = self() child = spawn(fn -> send current, {self(), 1 + 2} end) receive do {^child, 3} -> IO.puts "Received 3 back" end """ @spec spawn((() -> any)) :: pid def spawn(fun) do :erlang.spawn(fun) end @doc """ Spawns the given module and function passing the given args and returns its pid. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples spawn(SomeModule, :function, [1, 2, 3]) """ @spec spawn(module, atom, list) :: pid def spawn(module, fun, args) do :erlang.spawn(module, fun, args) end @doc """ Spawns the given function, links it to the current process and returns its pid. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples current = self() child = spawn_link(fn -> send current, {self(), 1 + 2} end) receive do {^child, 3} -> IO.puts "Received 3 back" end """ @spec spawn_link((() -> any)) :: pid def spawn_link(fun) do :erlang.spawn_link(fun) end @doc """ Spawns the given module and function passing the given args, links it to the current process and returns its pid. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples spawn_link(SomeModule, :function, [1, 2, 3]) """ @spec spawn_link(module, atom, list) :: pid def spawn_link(module, fun, args) do :erlang.spawn_link(module, fun, args) end @doc """ Spawns the given function, monitors it and returns its pid and monitoring reference. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples current = self() spawn_monitor(fn -> send current, {self(), 1 + 2} end) """ @spec spawn_monitor((() -> any)) :: {pid, reference} def spawn_monitor(fun) do :erlang.spawn_monitor(fun) end @doc """ Spawns the given module and function passing the given args, monitors it and returns its pid and monitoring reference. Check the `Process` and `Node` modules for other functions to handle processes, including spawning functions in nodes. Inlined by the compiler. ## Examples spawn_monitor(SomeModule, :function, [1, 2, 3]) """ @spec spawn_monitor(module, atom, list) :: {pid, reference} def spawn_monitor(module, fun, args) do :erlang.spawn_monitor(module, fun, args) end @doc """ A non-local return from a function. Check `Kernel.SpecialForms.try/1` for more information. Inlined by the compiler. """ @spec throw(term) :: no_return def throw(term) do :erlang.throw(term) end @doc """ Returns the tail of a list. Raises `ArgumentError` if the list is empty. Allowed in guard tests. Inlined by the compiler. ## Examples iex> tl([1, 2, 3, :go]) [2, 3, :go] """ @spec tl(maybe_improper_list) :: maybe_improper_list def tl(list) do :erlang.tl(list) end @doc """ Returns the integer part of `number`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> trunc(5.4) 5 iex> trunc(5.99) 5 """ @spec trunc(number) :: integer def trunc(number) do :erlang.trunc(number) end @doc """ Returns the size of a tuple. This operation happens in constant time. Allowed in guard tests. Inlined by the compiler. ## Examples iex> tuple_size {:a, :b, :c} 3 """ @spec tuple_size(tuple) :: non_neg_integer def tuple_size(tuple) do :erlang.tuple_size(tuple) end @doc """ Arithmetic addition. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 + 2 3 """ @spec (number + number) :: number def left + right do :erlang.+(left, right) end @doc """ Arithmetic subtraction. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 - 2 -1 """ @spec (number - number) :: number def left - right do :erlang.-(left, right) end @doc """ Arithmetic unary plus. Allowed in guard tests. Inlined by the compiler. ## Examples iex> +1 1 """ @spec (+number) :: number def (+value) do :erlang.+(value) end @doc """ Arithmetic unary minus. Allowed in guard tests. Inlined by the compiler. ## Examples iex> -2 -2 """ @spec (-number) :: number def (-value) do :erlang.-(value) end @doc """ Arithmetic multiplication. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 * 2 2 """ @spec (number * number) :: number def left * right do :erlang.*(left, right) end @doc """ Arithmetic division. The result is always a float. Use `div/2` and `rem/2` if you want an integer division or the remainder. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 / 2 0.5 iex> 2 / 1 2.0 """ @spec (number / number) :: float def left / right do :erlang./(left, right) end @doc """ Concatenates two lists. Allowed in guard tests. Inlined by the compiler. ## Examples iex> [1] ++ [2, 3] [1, 2, 3] iex> 'foo' ++ 'bar' 'foobar' """ @spec (list ++ term) :: maybe_improper_list def left ++ right do :erlang.++(left, right) end @doc """ Removes the first occurrence of an item on the left list for each item on the right. Allowed in guard tests. Inlined by the compiler. ## Examples iex> [1, 2, 3] -- [1, 2] [3] iex> [1, 2, 3, 2, 1] -- [1, 2, 2] [3, 1] """ @spec (list -- list) :: list def left -- right do :erlang.--(left, right) end @doc """ Boolean not. `arg` must be a boolean; if it's not, an `ArgumentError` exception is raised. Allowed in guard tests. Inlined by the compiler. ## Examples iex> not false true """ @spec not(boolean) :: boolean def not(arg) do :erlang.not(arg) end @doc """ Returns `true` if left is less than right. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 < 2 true """ @spec (term < term) :: boolean def left < right do :erlang.<(left, right) end @doc """ Returns `true` if left is more than right. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 > 2 false """ @spec (term > term) :: boolean def left > right do :erlang.>(left, right) end @doc """ Returns `true` if left is less than or equal to right. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 <= 2 true """ @spec (term <= term) :: boolean def left <= right do :erlang."=<"(left, right) end @doc """ Returns `true` if left is more than or equal to right. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 >= 2 false """ @spec (term >= term) :: boolean def left >= right do :erlang.>=(left, right) end @doc """ Returns `true` if the two items are equal. This operator considers 1 and 1.0 to be equal. For match semantics, use `===` instead. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 == 2 false iex> 1 == 1.0 true """ @spec (term == term) :: boolean def left == right do :erlang.==(left, right) end @doc """ Returns `true` if the two items are not equal. This operator considers 1 and 1.0 to be equal. For match comparison, use `!==` instead. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 != 2 true iex> 1 != 1.0 false """ @spec (term != term) :: boolean def left != right do :erlang."/="(left, right) end @doc """ Returns `true` if the two items are match. This operator gives the same semantics as the one existing in pattern matching, i.e., `1` and `1.0` are equal, but they do not match. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 === 2 false iex> 1 === 1.0 false """ @spec (term === term) :: boolean def left === right do :erlang."=:="(left, right) end @doc """ Returns `true` if the two items do not match. All terms in Elixir can be compared with each other. Allowed in guard tests. Inlined by the compiler. ## Examples iex> 1 !== 2 true iex> 1 !== 1.0 true """ @spec (term !== term) :: boolean def left !== right do :erlang."=/="(left, right) end @doc """ Gets the element at the zero-based `index` in `tuple`. Allowed in guard tests. Inlined by the compiler. ## Examples iex> tuple = {:foo, :bar, 3} iex> elem(tuple, 1) :bar """ @spec elem(tuple, non_neg_integer) :: term def elem(tuple, index) do :erlang.element(index + 1, tuple) end @doc """ Inserts `value` at the given zero-based `index` in `tuple`. Inlined by the compiler. ## Examples iex> tuple = {:foo, :bar, 3} iex> put_elem(tuple, 0, :baz) {:baz, :bar, 3} """ @spec put_elem(tuple, non_neg_integer, term) :: tuple def put_elem(tuple, index, value) do :erlang.setelement(index + 1, tuple, value) end ## Implemented in Elixir @doc """ Boolean or. If the first argument is `true`, `true` is returned; otherwise, the second argument is returned. Requires only the first argument to be a boolean since it short-circuits. If the first argument is not a boolean, an `ArgumentError` exception is raised. Allowed in guard tests. ## Examples iex> true or false true iex> false or 42 42 """ defmacro left or right do quote do: __op__(:orelse, unquote(left), unquote(right)) end @doc """ Boolean and. If the first argument is `false`, `false` is returned; otherwise, the second argument is returned. Requires only the first argument to be a boolean since it short-circuits. If the first argument is not a boolean, an `ArgumentError` exception is raised. Allowed in guard tests. ## Examples iex> true and false false iex> true and "yay!" "yay!" """ defmacro left and right do quote do: __op__(:andalso, unquote(left), unquote(right)) end @doc """ Boolean not. Receives any argument (not just booleans) and returns `true` if the argument is `false` or `nil`; returns `false` otherwise. Not allowed in guard clauses. ## Examples iex> !Enum.empty?([]) false iex> !List.first([]) true """ defmacro !(arg) defmacro !({:!, _, [arg]}) do optimize_boolean(quote do case unquote(arg) do x when x in [false, nil] -> false _ -> true end end) end defmacro !(arg) do optimize_boolean(quote do case unquote(arg) do x when x in [false, nil] -> true _ -> false end end) end @doc """ Concatenates two binaries. ## Examples iex> "foo" <> "bar" "foobar" The `<>` operator can also be used in pattern matching (and guard clauses) as long as the first part is a literal binary: iex> "foo" <> x = "foobar" iex> x "bar" `x <> "bar" = "foobar"` would have resulted in a `CompileError` exception. """ defmacro left <> right do concats = extract_concatenations({:<>, [], [left, right]}) quote do: <> end # Extracts concatenations in order to optimize many # concatenations into one single clause. defp extract_concatenations({:<>, _, [left, right]}) do [wrap_concatenation(left)|extract_concatenations(right)] end defp extract_concatenations(other) do [wrap_concatenation(other)] end defp wrap_concatenation(binary) when is_binary(binary) do binary end defp wrap_concatenation(other) do {:::, [], [other, {:binary, [], nil}]} end @doc """ Raises an exception. If the argument `msg` is a binary, it raises a `RuntimeError` exception using the given argument as message. If `msg` is an atom, it just calls `raise/2` with the atom as the first argument and `[]` as the second argument. If `msg` is anything else, raises an `ArgumentError` exception. ## Examples iex> raise "Oops" ** (RuntimeError) Oops try do 1 + :foo rescue x in [ArithmeticError] -> IO.puts "that was expected" raise x end """ defmacro raise(msg) do # Try to figure out the type at compilation time # to avoid dead code and make dialyzer happy. msg = case not is_binary(msg) and bootstraped?(Macro) do true -> Macro.expand(msg, __CALLER__) false -> msg end case msg do msg when is_binary(msg) -> quote do :erlang.error RuntimeError.exception(unquote(msg)) end {:<<>>, _, _} = msg -> quote do :erlang.error RuntimeError.exception(unquote(msg)) end alias when is_atom(alias) -> quote do :erlang.error unquote(alias).exception([]) end _ -> quote do case unquote(msg) do msg when is_binary(msg) -> :erlang.error RuntimeError.exception(msg) atom when is_atom(atom) -> :erlang.error atom.exception([]) %{__struct__: struct, __exception__: true} = other when is_atom(struct) -> :erlang.error other other -> message = "raise/1 expects an alias, string or exception as the first argument, got: #{inspect other}" :erlang.error ArgumentError.exception(message) end end end end @doc """ Raises an exception. Calls the `exception/1` function on the given argument (which has to be a module name like `ArgumentError` or `RuntimeError`) passing `attrs` as the attributes in order to retrieve the exception struct. Any module that contains a call to the `defexception/1` macro automatically implements the `exception/1` callback expected by `raise/2`. See the docs for `defexception/1` for more information. ## Examples iex> raise(ArgumentError, message: "Sample") ** (ArgumentError) Sample """ defmacro raise(exception, attrs) do quote do :erlang.error unquote(exception).exception(unquote(attrs)) end end @doc """ Raises an exception preserving a previous stacktrace. Works like `raise/1` but does not generate a new stacktrace. Notice that `System.stacktrace/0` returns the stacktrace of the last exception. That said, it is common to assign the stacktrace as the first expression inside a `rescue` clause as any other exception potentially raised (and rescued) between the rescue clause and the raise call may change the `System.stacktrace/0` value. ## Examples try do raise "Oops" rescue exception -> stacktrace = System.stacktrace if Exception.message(exception) == "Oops" do reraise exception, stacktrace end end """ defmacro reraise(msg, stacktrace) do # Try to figure out the type at compilation time # to avoid dead code and make dialyzer happy. case Macro.expand(msg, __CALLER__) do msg when is_binary(msg) -> quote do :erlang.raise :error, RuntimeError.exception(unquote(msg)), unquote(stacktrace) end {:<<>>, _, _} = msg -> quote do :erlang.raise :error, RuntimeError.exception(unquote(msg)), unquote(stacktrace) end alias when is_atom(alias) -> quote do :erlang.raise :error, unquote(alias).exception([]), unquote(stacktrace) end msg -> quote do stacktrace = unquote(stacktrace) case unquote(msg) do msg when is_binary(msg) -> :erlang.raise :error, RuntimeError.exception(msg), stacktrace atom when is_atom(atom) -> :erlang.raise :error, atom.exception([]), stacktrace %{__struct__: struct, __exception__: true} = other when is_atom(struct) -> :erlang.raise :error, other, stacktrace other -> message = "reraise/2 expects an alias, string or exception as the first argument, got: #{inspect other}" :erlang.error ArgumentError.exception(message) end end end end @doc """ Raises an exception preserving a previous stacktrace. `reraise/3` works like `reraise/2`, except it passes arguments to the `exception/1` function like explained in `raise/2`. ## Examples try do raise "Oops" rescue exception -> stacktrace = System.stacktrace reraise WrapperError, [exception: exception], stacktrace end """ defmacro reraise(exception, attrs, stacktrace) do quote do :erlang.raise :error, unquote(exception).exception(unquote(attrs)), unquote(stacktrace) end end @doc """ Matches the term on the left against the regular expression or string on the right. Returns `true` if `left` matches `right` (if it's a regular expression) or contains `right` (if it's a string). ## Examples iex> "abcd" =~ ~r/c(d)/ true iex> "abcd" =~ ~r/e/ false iex> "abcd" =~ "bc" true iex> "abcd" =~ "ad" false iex> "abcd" =~ "" true """ @spec (String.t =~ (String.t | Regex.t)) :: boolean def left =~ "" when is_binary(left), do: true def left =~ right when is_binary(left) and is_binary(right) do :binary.match(left, right) != :nomatch end def left =~ right when is_binary(left) do Regex.match?(right, left) end @doc ~S""" Inspects the given argument according to the `Inspect` protocol. The second argument is a keyword list with options to control inspection. ## Options `inspect/2` accepts a list of options that are internally translated to an `Inspect.Opts` struct. Check the docs for `Inspect.Opts` to see the supported options. ## Examples iex> inspect(:foo) ":foo" iex> inspect [1, 2, 3, 4, 5], limit: 3 "[1, 2, 3, ...]" iex> inspect("olá" <> <<0>>) "<<111, 108, 195, 161, 0>>" iex> inspect("olá" <> <<0>>, binaries: :as_strings) "\"olá\\0\"" iex> inspect("olá", binaries: :as_binaries) "<<111, 108, 195, 161>>" iex> inspect('bar') "'bar'" iex> inspect([0|'bar']) "[0, 98, 97, 114]" iex> inspect(100, base: :octal) "0o144" iex> inspect(100, base: :hex) "0x64" Note that the `Inspect` protocol does not necessarily return a valid representation of an Elixir term. In such cases, the inspected result must start with `#`. For example, inspecting a function will return: inspect fn a, b -> a + b end #=> #Function<...> """ @spec inspect(Inspect.t, Keyword.t) :: String.t def inspect(arg, opts \\ []) when is_list(opts) do opts = struct(Inspect.Opts, opts) limit = case opts.pretty do true -> opts.width false -> :infinity end IO.iodata_to_binary( Inspect.Algebra.format(Inspect.Algebra.to_doc(arg, opts), limit) ) end @doc """ Creates and updates structs. The `struct` argument may be an atom (which defines `defstruct`) or a `struct` itself. The second argument is any `Enumerable` that emits two-item tuples (key-value pairs) during enumeration. Keys in the `Enumerable` that don't exist in the struct are automatically discarded. This function is useful for dynamically creating and updating structs, as well as for converting maps to structs; in the latter case, just inserting the appropriate `:__struct__` field into the map may not be enough and `struct/2` should be used instead. ## Examples defmodule User do defstruct name: "john" end struct(User) #=> %User{name: "john"} opts = [name: "meg"] user = struct(User, opts) #=> %User{name: "meg"} struct(user, unknown: "value") #=> %User{name: "meg"} struct(User, %{name: "meg"}) #=> %User{name: "meg"} """ @spec struct(module | map, Enum.t) :: map def struct(struct, kv \\ []) def struct(struct, []) when is_atom(struct) or is_tuple(struct) do apply(struct, :__struct__, []) end def struct(struct, kv) when is_atom(struct) or is_tuple(struct) do struct(apply(struct, :__struct__, []), kv) end def struct(%{__struct__: _} = struct, kv) do Enum.reduce(kv, struct, fn {k, v}, acc -> case :maps.is_key(k, acc) and k != :__struct__ do true -> :maps.put(k, v, acc) false -> acc end end) end @doc """ Gets a value from a nested structure. Uses the `Access` protocol to traverse the structures according to the given `keys`, unless the `key` is a function. If a key is a function, the function will be invoked passing three arguments, the operation (`:get`), the data to be accessed, and a function to be invoked next. This means `get_in/2` can be extended to provide custom lookups. The downside is that functions cannot be stored as keys in the accessed data structures. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> get_in(users, ["john", :age]) 27 In case any of entries in the middle returns `nil`, `nil` will be returned as per the Access protocol: iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> get_in(users, ["unknown", :age]) nil When one of the keys is a function, the function is invoked. In the example below, we use a function to get all the maps inside a list: iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}] iex> all = fn :get, data, next -> Enum.map(data, next) end iex> get_in(users, [all, :age]) [27, 23] If the previous value before invoking the function is `nil`, the function *will* receive nil as a value and must handle it accordingly. """ @spec get_in(Access.t, nonempty_list(term)) :: term def get_in(data, keys) def get_in(data, [h]) when is_function(h), do: h.(:get, data, &(&1)) def get_in(data, [h|t]) when is_function(h), do: h.(:get, data, &get_in(&1, t)) def get_in(nil, [_]), do: nil def get_in(nil, [_|t]), do: get_in(nil, t) def get_in(data, [h]), do: Access.get(data, h) def get_in(data, [h|t]), do: get_in(Access.get(data, h), t) @doc """ Puts a value in a nested structure. Uses the `Access` protocol to traverse the structures according to the given `keys`, unless the `key` is a function. If the key is a function, it will be invoked as specified in `get_and_update_in/3`. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> put_in(users, ["john", :age], 28) %{"john" => %{age: 28}, "meg" => %{age: 23}} In case any of entries in the middle returns `nil`, an error will be raised when trying to access it next. """ @spec put_in(Access.t, nonempty_list(term), term) :: Access.t def put_in(data, keys, value) do elem(get_and_update_in(data, keys, fn _ -> {nil, value} end), 1) end @doc """ Updates a key in a nested structure. Uses the `Access` protocol to traverse the structures according to the given `keys`, unless the `key` is a function. If the key is a function, it will be invoked as specified in `get_and_update_in/3`. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> update_in(users, ["john", :age], &(&1 + 1)) %{"john" => %{age: 28}, "meg" => %{age: 23}} In case any of entries in the middle returns `nil`, an error will be raised when trying to access it next. """ @spec update_in(Access.t, nonempty_list(term), (term -> term)) :: Access.t def update_in(data, keys, fun) do elem(get_and_update_in(data, keys, fn x -> {nil, fun.(x)} end), 1) end @doc """ Gets a value and updates a nested structure. It expects a tuple to be returned, containing the value retrieved and the update one. Uses the `Access` protocol to traverse the structures according to the given `keys`, unless the `key` is a function. If a key is a function, the function will be invoked passing three arguments, the operation (`:get_and_update`), the data to be accessed, and a function to be invoked next. This means `get_and_update_in/3` can be extended to provide custom lookups. The downside is that functions cannot be stored as keys in the accessed data structures. ## Examples This function is useful when there is a need to retrieve the current value (or something calculated in function of the current value) and update it at the same time. For example, it could be used to increase the age of a user by one and return the previous age in one pass: iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> get_and_update_in(users, ["john", :age], &{&1, &1 + 1}) {27, %{"john" => %{age: 28}, "meg" => %{age: 23}}} When one of the keys is a function, the function is invoked. In the example below, we use a function to get and increment all ages inside a list: iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}] iex> all = fn :get_and_update, data, next -> ...> Enum.map(data, next) |> :lists.unzip ...> end iex> get_and_update_in(users, [all, :age], &{&1, &1 + 1}) {[27, 23], [%{name: "john", age: 28}, %{name: "meg", age: 24}]} If the previous value before invoking the function is `nil`, the function *will* receive `nil` as a value and must handle it accordingly (be it by failing or providing a sane default). """ @spec get_and_update_in(Access.t, nonempty_list(term), (term -> {get, term})) :: {get, Access.t} when get: var def get_and_update_in(data, keys, fun) def get_and_update_in(data, [h], fun) when is_function(h), do: h.(:get_and_update, data, fun) def get_and_update_in(data, [h|t], fun) when is_function(h), do: h.(:get_and_update, data, &get_and_update_in(&1, t, fun)) def get_and_update_in(data, [h], fun), do: Access.get_and_update(data, h, fun) def get_and_update_in(data, [h|t], fun), do: Access.get_and_update(data, h, &get_and_update_in(&1, t, fun)) @doc """ Puts a value in a nested structure via the given `path`. This is similar to `put_in/3`, except the path is extracted via a macro rather than passing a list. For example: put_in(opts[:foo][:bar], :baz) Is equivalent to: put_in(opts, [:foo, :bar], :baz) Note that in order for this macro to work, the complete path must always be visible by this macro. For more information about the supported path expressions, please check `get_and_update_in/2` docs. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> put_in(users["john"][:age], 28) %{"john" => %{age: 28}, "meg" => %{age: 23}} iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> put_in(users["john"].age, 28) %{"john" => %{age: 28}, "meg" => %{age: 23}} """ defmacro put_in(path, value) do [h|t] = unnest(path, [], "put_in/2") expr = nest_get_and_update_in(h, t, quote(do: fn _ -> {nil, unquote(value)} end)) quote do: :erlang.element(2, unquote(expr)) end @doc """ Updates a nested structure via the given `path`. This is similar to `update_in/3`, except the path is extracted via a macro rather than passing a list. For example: update_in(opts[:foo][:bar], &(&1 + 1)) Is equivalent to: update_in(opts, [:foo, :bar], &(&1 + 1)) Note that in order for this macro to work, the complete path must always be visible by this macro. For more information about the supported path expressions, please check `get_and_update_in/2` docs. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> update_in(users["john"][:age], &(&1 + 1)) %{"john" => %{age: 28}, "meg" => %{age: 23}} iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> update_in(users["john"].age, &(&1 + 1)) %{"john" => %{age: 28}, "meg" => %{age: 23}} """ defmacro update_in(path, fun) do [h|t] = unnest(path, [], "update_in/2") expr = nest_get_and_update_in(h, t, quote(do: fn x -> {nil, unquote(fun).(x)} end)) quote do: :erlang.element(2, unquote(expr)) end @doc """ Gets a value and updates a nested data structure via the given `path`. This is similar to `get_and_update_in/3`, except the path is extracted via a macro rather than passing a list. For example: get_and_update_in(opts[:foo][:bar], &{&1, &1 + 1}) Is equivalent to: get_and_update_in(opts, [:foo, :bar], &{&1, &1 + 1}) Note that in order for this macro to work, the complete path must always be visible by this macro. See the Paths section below. ## Examples iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} iex> get_and_update_in(users["john"].age, &{&1, &1 + 1}) {27, %{"john" => %{age: 28}, "meg" => %{age: 23}}} ## Paths A path may start with a variable, local or remote call, and must be followed by one or more: * `foo[bar]` - access a field; in case an intermediate field is not present or returns `nil`, an empty map is used * `foo.bar` - access a map/struct field; in case the field is not present, an error is raised Here are some valid paths: users["john"][:age] users["john"].age User.all["john"].age all_users()["john"].age Here are some invalid ones: # Does a remote call after the initial value users["john"].do_something(arg1, arg2) # Does not access any field users """ defmacro get_and_update_in(path, fun) do [h|t] = unnest(path, [], "get_and_update_in/2") nest_get_and_update_in(h, t, fun) end defp nest_get_and_update_in([], fun), do: fun defp nest_get_and_update_in(list, fun) do quote do fn x -> unquote(nest_get_and_update_in(quote(do: x), list, fun)) end end end defp nest_get_and_update_in(h, [{:access, key}|t], fun) do quote do Access.get_and_update( unquote(h), unquote(key), unquote(nest_get_and_update_in(t, fun)) ) end end defp nest_get_and_update_in(h, [{:map, key}|t], fun) do quote do Access.Map.get_and_update!(unquote(h), unquote(key), unquote(nest_get_and_update_in(t, fun))) end end defp unnest({{:., _, [Access, :get]}, _, [expr, key]}, acc, kind) do unnest(expr, [{:access, key}|acc], kind) end defp unnest({{:., _, [expr, key]}, _, []}, acc, kind) when is_tuple(expr) and :erlang.element(1, expr) != :__aliases__ and :erlang.element(1, expr) != :__MODULE__ do unnest(expr, [{:map, key}|acc], kind) end defp unnest(other, [], kind) do raise ArgumentError, "expected expression given to #{kind} to access at least one element, got: #{Macro.to_string other}" end defp unnest(other, acc, kind) do case proper_start?(other) do true -> [other|acc] false -> raise ArgumentError, "expression given to #{kind} must start with a variable, local or remote call " <> "and be followed by an element access, got: #{Macro.to_string other}" end end defp proper_start?({{:., _, [expr, _]}, _, _args}) when is_atom(expr) when :erlang.element(1, expr) == :__aliases__ when :erlang.element(1, expr) == :__MODULE__, do: true defp proper_start?({atom, _, _args}) when is_atom(atom), do: true defp proper_start?(other), do: not is_tuple(other) @doc """ Converts the argument to a string according to the `String.Chars` protocol. This is the function invoked when there is string interpolation. ## Examples iex> to_string(:foo) "foo" """ # If it is a binary at compilation time, simply return it. defmacro to_string(arg) when is_binary(arg), do: arg defmacro to_string(arg) do quote do: String.Chars.to_string(unquote(arg)) end @doc """ Converts the argument to a char list according to the `List.Chars` protocol. ## Examples iex> to_char_list(:foo) 'foo' """ defmacro to_char_list(arg) do quote do: List.Chars.to_char_list(unquote(arg)) end @doc """ Returns `true` if `term` is `nil`, `false` otherwise. Allowed in guard clauses. ## Examples iex> is_nil(1) false iex> is_nil(nil) true """ defmacro is_nil(term) do quote do: unquote(term) == nil end @doc """ A convenience macro that checks if the right side (an expression) matches the left side (a pattern). ## Examples iex> match?(1, 1) true iex> match?(1, 2) false iex> match?({1, _}, {1, 2}) true iex> map = %{a: 1, b: 2} iex> match?(%{a: _}, map) true iex> a = 1 iex> match?(^a, 1) true `match?/2` is very useful when filtering of finding a value in an enumerable: list = [{:a, 1}, {:b, 2}, {:a, 3}] Enum.filter list, &match?({:a, _}, &1) #=> [{:a, 1}, {:a, 3}] Guard clauses can also be given to the match: list = [{:a, 1}, {:b, 2}, {:a, 3}] Enum.filter list, &match?({:a, x} when x < 2, &1) #=> [{:a, 1}] However, variables assigned in the match will not be available outside of the function call (unlike regular pattern matching with the `=` operator): iex> match?(_x, 1) true iex> binding() [] """ defmacro match?(pattern, expr) # Special case where underscore, which always matches, is passed as the first # argument. defmacro match?({:_, _, atom}, _right) when is_atom(atom) do true end defmacro match?(left, right) do quote do case unquote(right) do unquote(left) -> true _ -> false end end end @doc """ Reads and writes attributes of the current module. The canonical example for attributes is annotating that a module implements the OTP behaviour called `gen_server`: defmodule MyServer do @behaviour :gen_server # ... callbacks ... end By default Elixir supports all the module attributes supported by Erlang, but custom attributes can be used as well: defmodule MyServer do @my_data 13 IO.inspect @my_data #=> 13 end Unlike Erlang, such attributes are not stored in the module by default since it is common in Elixir to use custom attributes to store temporary data that will be available at compile-time. Custom attributes may be configured to behave closer to Erlang by using `Module.register_attribute/3`. Finally, notice that attributes can also be read inside functions: defmodule MyServer do @my_data 11 def first_data, do: @my_data @my_data 13 def second_data, do: @my_data end MyServer.first_data #=> 11 MyServer.second_data #=> 13 It is important to note that reading an attribute takes a snapshot of its current value. In other words, the value is read at compilation time and not at runtime. Check the `Module` module for other functions to manipulate module attributes. """ defmacro @(expr) # Typespecs attributes are special cased by the compiler so far defmacro @({name, _, args}) do # Check for Macro as it is compiled later than Module case bootstraped?(Module) do false -> nil true -> assert_module_scope(__CALLER__, :@, 1) function? = __CALLER__.function != nil case not function? and __CALLER__.context == :match do false -> nil true -> raise ArgumentError, "invalid write attribute syntax, you probably meant to use: @#{name} expression" end case is_list(args) and length(args) == 1 and typespec(name) do false -> do_at(args, name, function?, __CALLER__) macro -> case bootstraped?(Kernel.Typespec) do false -> nil true -> quote do: Kernel.Typespec.unquote(macro)(unquote(hd(args))) end end end end # @attribute value defp do_at([arg], name, function?, env) do case function? do true -> raise ArgumentError, "cannot set attribute @#{name} inside function/macro" false -> case name do :behavior -> :elixir_errors.warn env.line, env.file, "@behavior attribute is not supported, please use @behaviour instead" _ -> :ok end quote do: Module.put_attribute(__MODULE__, unquote(name), unquote(arg)) end end # @attribute or @attribute() defp do_at(args, name, function?, env) when is_atom(args) or args == [] do stack = env_stacktrace(env) case function? do true -> attr = Module.get_attribute(env.module, name, stack) try do :elixir_quote.escape(attr, false) rescue e in [ArgumentError] -> raise ArgumentError, "cannot inject attribute @#{name} into function/macro because " <> Exception.message(e) else {val, _} -> val end false -> escaped = case stack do [] -> [] _ -> Macro.escape(stack) end quote do: Module.get_attribute(__MODULE__, unquote(name), unquote(escaped)) end end # All other cases defp do_at(args, name, _function?, _env) do raise ArgumentError, "expected 0 or 1 argument for @#{name}, got: #{length(args)}" end defp typespec(:type), do: :deftype defp typespec(:typep), do: :deftypep defp typespec(:opaque), do: :defopaque defp typespec(:spec), do: :defspec defp typespec(:callback), do: :defcallback defp typespec(_), do: false @doc """ Returns the binding for the given context as a keyword list. In the returned result, keys are variable names and values are the corresponding variable values. If the given `context` is `nil` (by default it is), the binding for the current context is returned. ## Examples iex> x = 1 iex> binding() [x: 1] iex> x = 2 iex> binding() [x: 2] iex> binding(:foo) [] iex> var!(x, :foo) = 1 1 iex> binding(:foo) [x: 1] """ defmacro binding(context \\ nil) do in_match? = Macro.Env.in_match?(__CALLER__) for {v, c} <- __CALLER__.vars, c == context do {v, wrap_binding(in_match?, {v, [], c})} end end defp wrap_binding(true, var) do quote do: ^(unquote(var)) end defp wrap_binding(_, var) do var end @doc """ Provides an `if` macro. This macro expects the first argument to be a condition and the second argument to be a keyword list. ## One-liner examples if(foo, do: bar) In the example above, `bar` will be returned if `foo` evaluates to `true` (i.e., it is neither `false` nor `nil`). Otherwise, `nil` will be returned. An `else` option can be given to specify the opposite: if(foo, do: bar, else: baz) ## Blocks examples It's also possible to pass a block to the `if` macro. The first example above would be translated to: if foo do bar end Note that `do/end` become delimiters. The second example would translate to: if foo do bar else baz end In order to compare more than two clauses, the `cond/1` macro has to be used. """ defmacro if(condition, clauses) do do_clause = Keyword.get(clauses, :do, nil) else_clause = Keyword.get(clauses, :else, nil) optimize_boolean(quote do case unquote(condition) do x when x in [false, nil] -> unquote(else_clause) _ -> unquote(do_clause) end end) end @doc """ Provides an `unless` macro. This macro evaluates and returns the `do` block passed in as the second argument unless `clause` evaluates to `true`. Otherwise, it returns the value of the `else` block if present or `nil` if not. See also `if/2`. ## Examples iex> unless(Enum.empty?([]), do: "Hello") nil iex> unless(Enum.empty?([1, 2, 3]), do: "Hello") "Hello" iex> unless Enum.sum([2, 2]) == 5 do ...> "Math still works" ...> else ...> "Math is broken" ...> end "Math still works" """ defmacro unless(clause, options) do do_clause = Keyword.get(options, :do, nil) else_clause = Keyword.get(options, :else, nil) quote do if(unquote(clause), do: unquote(else_clause), else: unquote(do_clause)) end end @doc """ Destructures two lists, assigning each term in the right one to the matching term in the left one. Unlike pattern matching via `=`, if the sizes of the left and right lists don't match, destructuring simply stops instead of raising an error. ## Examples iex> destructure([x, y, z], [1, 2, 3, 4, 5]) iex> {x, y, z} {1, 2, 3} In the example above, even though the right list has more entries than the left one, destructuring works fine. If the right list is smaller, the remaining items are simply set to `nil`: iex> destructure([x, y, z], [1]) iex> {x, y, z} {1, nil, nil} The left-hand side supports any expression you would use on the left-hand side of a match: x = 1 destructure([^x, y, z], [1, 2, 3]) The example above will only work if `x` matches the first value in the right list. Otherwise, it will raise a `MatchError` (like the `=` operator would do). """ defmacro destructure(left, right) when is_list(left) do Enum.reduce left, right, fn item, acc -> {:case, meta, args} = quote do case unquote(acc) do [h|t] -> unquote(item) = h t other when other == [] or other == nil -> unquote(item) = nil [] end end {:case, meta, args} end end @doc """ Returns a range with the specified start and end. Both ends are included. ## Examples iex> 0 in 1..3 false iex> 1 in 1..3 true iex> 2 in 1..3 true iex> 3 in 1..3 true """ defmacro first .. last do {:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} end @doc """ Provides a short-circuit operator that evaluates and returns the second expression only if the first one evaluates to `true` (i.e., it is not `nil` nor `false`). Returns the first expression otherwise. Not allowed in guard clauses. ## Examples iex> Enum.empty?([]) && Enum.empty?([]) true iex> List.first([]) && true nil iex> Enum.empty?([]) && List.first([1]) 1 iex> false && throw(:bad) false Note that, unlike Erlang's `and` operator, this operator accepts any expression as the first argument, not only booleans. """ defmacro left && right do quote do case unquote(left) do x when x in [false, nil] -> x _ -> unquote(right) end end end @doc """ Provides a short-circuit operator that evaluates and returns the second expression only if the first one does not evaluate to `true` (i.e., it is either `nil` or `false`). Returns the first expression otherwise. Not allowed in guard clauses. ## Examples iex> Enum.empty?([1]) || Enum.empty?([1]) false iex> List.first([]) || true true iex> Enum.empty?([1]) || 1 1 iex> Enum.empty?([]) || throw(:bad) true Note that, unlike Erlang's `or` operator, this operator accepts any expression as the first argument, not only booleans. """ defmacro left || right do quote do case unquote(left) do x when x in [false, nil] -> unquote(right) x -> x end end end @doc """ Pipe operator. This operator introduces the expression on the left-hand side as the first argument to the function call on the right-hand side. ## Examples iex> [1, [2], 3] |> List.flatten() [1, 2, 3] The example above is the same as calling `List.flatten([1, [2], 3])`. The `|>` operator is mostly useful when there is a desire to execute a series of operations resembling a pipeline: iex> [1, [2], 3] |> List.flatten |> Enum.map(fn x -> x * 2 end) [2, 4, 6] In the example above, the list `[1, [2], 3]` is passed as the first argument to the `List.flatten/1` function, then the flattened list is passed as the first argument to the `Enum.map/2` function which doubles each element of the list. In other words, the expression above simply translates to: Enum.map(List.flatten([1, [2], 3]), fn x -> x * 2 end) Beware of operator precedence when using the pipe operator. For example, the following expression: String.graphemes "Hello" |> Enum.reverse Translates to: String.graphemes("Hello" |> Enum.reverse) which results in an error as the `Enumerable` protocol is not defined for binaries. Adding explicit parentheses resolves the ambiguity: String.graphemes("Hello") |> Enum.reverse Or, even better: "Hello" |> String.graphemes |> Enum.reverse """ defmacro left |> right do [{h, _}|t] = Macro.unpipe({:|>, [], [left, right]}) :lists.foldl fn {x, pos}, acc -> Macro.pipe(acc, x, pos) end, h, t end @doc """ Returns `true` if `module` is loaded and contains a public `function` with the given `arity`, otherwise `false`. Note that this function does not load the module in case it is not loaded. Check `Code.ensure_loaded/1` for more information. ## Examples iex> function_exported?(Enum, :member?, 2) true """ @spec function_exported?(atom | tuple, atom, arity) :: boolean def function_exported?(module, function, arity) do :erlang.function_exported(module, function, arity) end @doc """ Returns `true` if `module` is loaded and contains a public `macro` with the given `arity`, otherwise `false`. Note that this function does not load the module in case it is not loaded. Check `Code.ensure_loaded/1` for more information. ## Examples iex> macro_exported?(Kernel, :use, 2) true """ @spec macro_exported?(atom, atom, integer) :: boolean def macro_exported?(module, macro, arity) do case :code.is_loaded(module) do {:file, _} -> :lists.member({macro, arity}, module.__info__(:macros)) _ -> false end end @doc """ Checks if the element on the left-hand side is a member of the collection on the right-hand side. ## Examples iex> x = 1 iex> x in [1, 2, 3] true This operator (which is a macro) simply translates to a call to `Enum.member?/2`. The example above would translate to: Enum.member?([1, 2, 3], x) ## Guards The `in` operator can be used in guard clauses as long as the right-hand side is a range or a list. In such cases, Elixir will expand the operator to a valid guard expression. For example: when x in [1, 2, 3] translates to: when x === 1 or x === 2 or x === 3 When using ranges: when x in 1..3 translates to: when x >= 1 and x <= 3 """ defmacro left in right do in_module? = (__CALLER__.context == nil) right = case bootstraped?(Macro) and not in_module? do true -> Macro.expand(right, __CALLER__) false -> right end case right do _ when in_module? -> quote do: Elixir.Enum.member?(unquote(right), unquote(left)) [] -> false [h|t] -> :lists.foldr(fn x, acc -> quote do unquote(comp(left, x)) or unquote(acc) end end, comp(left, h), t) {:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} -> in_range(left, Macro.expand(first, __CALLER__), Macro.expand(last, __CALLER__)) _ -> raise ArgumentError, <<"invalid args for operator in, it expects a compile time list ", "or range on the right side when used in guard expressions, got: ", Macro.to_string(right) :: binary>> end end defp in_range(left, first, last) do case opt_in?(first) and opt_in?(last) do true -> case first <= last do true -> increasing_compare(left, first, last) false -> decreasing_compare(left, first, last) end false -> quote do (:erlang."=<"(unquote(first), unquote(last)) and unquote(increasing_compare(left, first, last))) or (:erlang."<"(unquote(last), unquote(first)) and unquote(decreasing_compare(left, first, last))) end end end defp opt_in?(x), do: is_integer(x) or is_float(x) or is_atom(x) defp comp(left, right) do quote(do: :erlang."=:="(unquote(left), unquote(right))) end defp increasing_compare(var, first, last) do quote do :erlang.">="(unquote(var), unquote(first)) and :erlang."=<"(unquote(var), unquote(last)) end end defp decreasing_compare(var, first, last) do quote do :erlang."=<"(unquote(var), unquote(first)) and :erlang.">="(unquote(var), unquote(last)) end end @doc """ When used inside quoting, marks that the given variable should not be hygienized. The argument can be either a variable unquoted or in standard tuple form `{name, meta, context}`. Check `Kernel.SpecialForms.quote/2` for more information. """ defmacro var!(var, context \\ nil) defmacro var!({name, meta, atom}, context) when is_atom(name) and is_atom(atom) do do_var!(name, meta, context, __CALLER__) end defmacro var!(x, _context) do raise ArgumentError, "expected a var to be given to var!, got: #{Macro.to_string(x)}" end defp do_var!(name, meta, context, env) do # Remove counter and force them to be vars meta = :lists.keydelete(:counter, 1, meta) meta = :lists.keystore(:var, 1, meta, {:var, true}) case Macro.expand(context, env) do x when is_atom(x) -> {name, meta, x} x -> raise ArgumentError, "expected var! context to expand to an atom, got: #{Macro.to_string(x)}" end end @doc """ When used inside quoting, marks that the given alias should not be hygienized. This means the alias will be expanded when the macro is expanded. Check `Kernel.SpecialForms.quote/2` for more information. """ defmacro alias!(alias) defmacro alias!(alias) when is_atom(alias) do alias end defmacro alias!({:__aliases__, meta, args}) do # Simply remove the alias metadata from the node # so it does not affect expansion. {:__aliases__, :lists.keydelete(:alias, 1, meta), args} end ## Definitions implemented in Elixir @doc ~S""" Defines a module given by name with the given contents. This macro defines a module with the given `alias` as its name and with the given contents. It returns a tuple with four elements: * `:module` * the module name * the binary contents of the module * the result of evaluating the contents block ## Examples iex> defmodule Foo do ...> def bar, do: :baz ...> end iex> Foo.bar :baz ## Nesting Nesting a module inside another module affects the name of the nested module: defmodule Foo do defmodule Bar do end end In the example above, two modules - `Foo` and `Foo.Bar` - are created. When nesting, Elixir automatically creates an alias to the inner module, allowing the second module `Foo.Bar` to be accessed as `Bar` in the same lexical scope where it's defined (the `Foo` module). If the `Foo.Bar` module is moved somewhere else, the references to `Bar` in the `Foo` module need to be updated to the fully-qualified name (`Foo.Bar`) or an alias has to be explicitly set in the `Foo` module with the help of `Kernel.SpecialForms.alias/2`. defmodule Foo.Bar do # code end defmodule Foo do alias Foo.Bar # code here can refer to `Foo.Bar` as just `Bar` end ## Dynamic names Elixir module names can be dynamically generated. This is very useful when working with macros. For instance, one could write: defmodule String.to_atom("Foo#{1}") do # contents ... end Elixir will accept any module name as long as the expression passed as the first argument to `defmodule/2` evaluates to an atom. Note that, when a dynamic name is used, Elixir won't nest the name under the current module nor automatically set up an alias. """ defmacro defmodule(alias, do: block) do env = __CALLER__ boot? = bootstraped?(Macro) expanded = case boot? do true -> Macro.expand(alias, env) false -> alias end {expanded, with_alias} = case boot? and is_atom(expanded) do true -> # Expand the module considering the current environment/nesting full = expand_module(alias, expanded, env) # Generate the alias for this module definition {new, old} = module_nesting(env.module, full) meta = [defined: full, context: env.module] ++ alias_meta(alias) {full, {:alias, meta, [old, [as: new, warn: false]]}} false -> {expanded, nil} end {escaped, _} = :elixir_quote.escape(block, false) module_vars = module_vars(env.vars, 0) quote do unquote(with_alias) :elixir_module.compile(unquote(expanded), unquote(escaped), unquote(module_vars), __ENV__) end end defp alias_meta({:__aliases__, meta, _}), do: meta defp alias_meta(_), do: [] # defmodule :foo defp expand_module(raw, _module, _env) when is_atom(raw), do: raw # defmodule Elixir.Alias defp expand_module({:__aliases__, _, [:Elixir|t]}, module, _env) when t != [], do: module # defmodule Alias in root defp expand_module({:__aliases__, _, _}, module, %{module: nil}), do: module # defmodule Alias nested defp expand_module({:__aliases__, _, t}, _module, env), do: :elixir_aliases.concat([env.module|t]) # defmodule _ defp expand_module(_raw, module, env), do: :elixir_aliases.concat([env.module, module]) # quote vars to be injected into the module definition defp module_vars([{key, kind}|vars], counter) do var = case is_atom(kind) do true -> {key, [], kind} false -> {key, [counter: kind], nil} end under = String.to_atom(<<"_@", :erlang.integer_to_binary(counter)::binary>>) args = [key, kind, under, var] [{:{}, [], args}|module_vars(vars, counter+1)] end defp module_vars([], _counter) do [] end # Gets two modules names and return an alias # which can be passed down to the alias directive # and it will create a proper shortcut representing # the given nesting. # # Examples: # # module_nesting('Elixir.Foo.Bar', 'Elixir.Foo.Bar.Baz.Bat') # {'Elixir.Baz', 'Elixir.Foo.Bar.Baz'} # # In case there is no nesting/no module: # # module_nesting(nil, 'Elixir.Foo.Bar.Baz.Bat') # {false, 'Elixir.Foo.Bar.Baz.Bat'} # defp module_nesting(nil, full), do: {false, full} defp module_nesting(prefix, full) do case split_module(prefix) do [] -> {false, full} prefix -> module_nesting(prefix, split_module(full), [], full) end end defp module_nesting([x|t1], [x|t2], acc, full), do: module_nesting(t1, t2, [x|acc], full) defp module_nesting([], [h|_], acc, _full), do: {String.to_atom(<<"Elixir.", h::binary>>), :elixir_aliases.concat(:lists.reverse([h|acc]))} defp module_nesting(_, _, _acc, full), do: {false, full} defp split_module(atom) do case :binary.split(Atom.to_string(atom), ".", [:global]) do ["Elixir"|t] -> t _ -> [] end end @doc """ Defines a function with the given name and body. ## Examples defmodule Foo do def bar, do: :baz end Foo.bar #=> :baz A function that expects arguments can be defined as follows: defmodule Foo do def sum(a, b) do a + b end end In the example above, a `sum/2` function is defined; this function receives two arguments and returns their sum. """ defmacro def(call, expr \\ nil) do define(:def, call, expr, __CALLER__) end @doc """ Defines a private function with the given name and body. Private functions are only accessible from within the module in which they are defined. Trying to access a private function from outside the module it's defined in results in an `UndefinedFunctionError` exception. Check `def/2` for more information. ## Examples defmodule Foo do def bar do sum(1, 2) end defp sum(a, b), do: a + b end Foo.bar #=> 3 Foo.sum(1, 2) #=> ** (UndefinedFunctionError) undefined function: Foo.sum/2 """ defmacro defp(call, expr \\ nil) do define(:defp, call, expr, __CALLER__) end @doc """ Defines a macro with the given name and body. ## Examples defmodule MyLogic do defmacro unless(expr, opts) do quote do if !unquote(expr), unquote(opts) end end end require MyLogic MyLogic.unless false do IO.puts "It works" end """ defmacro defmacro(call, expr \\ nil) do define(:defmacro, call, expr, __CALLER__) end @doc """ Defines a private macro with the given name and body. Private macros are only accessible from the same module in which they are defined. Check `defmacro/2` for more information. """ defmacro defmacrop(call, expr \\ nil) do define(:defmacrop, call, expr, __CALLER__) end defp define(kind, call, expr, env) do assert_module_scope(env, kind, 2) assert_no_function_scope(env, kind, 2) line = env.line {call, uc} = :elixir_quote.escape(call, true) {expr, ue} = :elixir_quote.escape(expr, true) # Do not check clauses if any expression was unquoted check_clauses = not(ue or uc) pos = :elixir_locals.cache_env(env) quote do :elixir_def.store_definition(unquote(line), unquote(kind), unquote(check_clauses), unquote(call), unquote(expr), unquote(pos)) end end @doc """ Defines a struct. A struct is a tagged map that allows developers to provide default values for keys, tags to be used in polymorphic dispatches and compile time assertions. The only thing needed to define a struct is a `__struct__/0` function that returns a map with the struct fields and their default values. `defstruct/1` is a convenience macro which defines such a function (as well as a `t` type and deriving conveniences). When using `defstruct/1`, a struct named like the enclosing module is defined. For more information about structs, please check `Kernel.SpecialForms.%/2`. ## Examples defmodule User do defstruct name: nil, age: nil end Struct fields are evaluated at compile-time, which allows them to be dynamic. In the example below, `10 + 11` is evaluated at compile-time and the age field is stored with value `21`: defmodule User do defstruct name: nil, age: 10 + 11 end The `fields` argument is usually a keyword list with fields as keys and default values as corresponding values. `defstruct/1` also supports a list of atoms as its argument: in that case, the atoms in the list will be used as the struct's fields and they will all default to `nil`. defmodule Post do defstruct [:title, :content, :author] end ## Deriving Although structs are maps, by default structs do not implement any of the protocols implemented for maps. For example, attempting to use a protocol with the `User` struct leads to an error: john = %User{name: "John"} MyProtocol.call(john) ** (Protocol.UndefinedError) protocol MyProtocol not implemented for %User{...} `defstruct/1`, however, allows protocol implementations to be *derived*. This can be done by defining a `@derive` attribute as a list before invoking `defstruct/1`: defmodule User do @derive [MyProtocol] defstruct name: nil, age: 10 + 11 end MyProtocol.call(john) #=> works For each protocol in the `@derive` list, Elixir will assert there is an implementation of that protocol for any (regardless if fallback to any is true) and check if the any implementation defines a `__deriving__/3` callback. If so, the callback is invoked, otherwise an implementation that simply points to the any implementation is automatically derived. ## Types It is recommended to define types for structs. By convention such type is called `t`. To define a struct inside a type, the struct literal syntax is used: defmodule User do defstruct name: "John", age: 25 @type t :: %User{name: String.t, age: non_neg_integer} end It is recommended to only use the struct syntax when defining the struct's type. When referring to another struct it's better to use `User.t`instead of `%User{}`. The types of the struct fields that are not included in the struct's type default to `term`. Structs whose internal structure is private to the local module (pattern matching them or directly accessing their fields should not be allowed) should use the `@opaque` attribute. Structs whose internal structure is public should use `@type`. See `Kernel.Typespec` for more information on opaque types. """ defmacro defstruct(fields) do quote bind_quoted: [fields: fields] do fields = Kernel.Def.struct(__MODULE__, fields) @struct fields case Module.get_attribute(__MODULE__, :derive) do [] -> :ok derive -> Protocol.__derive__(derive, __MODULE__, __ENV__) end def __struct__() do @struct end fields end end @doc ~S""" Defines an exception. Exceptions are structs backed by a module that implements the `Exception` behaviour. The `Exception` behaviour requires two functions to be implemented: * `exception/1` - receives the arguments given to `raise/2` and returns the exception struct. The default implementation accepts either a set of keyword arguments that is merged into the struct or a string to be used as the exception's message. * `message/1` - receives the exception struct and must return its message. Most commonly exceptions have a message field which by default is accessed by this function. However, if an exception does not have a message field, this function must be explicitly implemented. Since exceptions are structs, the API supported by `defstruct/1` is also available in `defexception/1`. ## Raising exceptions The most common way to raise an exception is via `raise/2`: defmodule MyAppError do defexception [:message] end value = [:hello] raise MyAppError, message: "did not get what was expected, got: #{inspect value}" In many cases it is more convenient to pass the expected value to `raise/2` and generate the message in the `exception/1` callback: defmodule MyAppError do defexception [:message] def exception(value) do msg = "did not get what was expected, got: #{inspect value}" %MyAppError{message: msg} end end raise MyAppError, value The example above shows the preferred strategy for customizing exception messages. """ defmacro defexception(fields) do fields = case is_list(fields) do true -> [{:__exception__, true}|fields] false -> quote(do: [{:__exception__, true}] ++ unquote(fields)) end quote do @behaviour Exception fields = defstruct unquote(fields) if Map.has_key?(fields, :message) do @spec message(Exception.t) :: String.t def message(exception) do exception.message end defoverridable message: 1 @spec exception(String.t) :: Exception.t def exception(msg) when is_binary(msg) do exception(message: msg) end end @spec exception(Keyword.t) :: Exception.t def exception(args) when is_list(args) do Kernel.struct(__struct__, args) end defoverridable exception: 1 end end @doc """ Defines a protocol. A protocol specifies an API that should be defined by its implementations. ## Examples In Elixir, only `false` and `nil` are considered falsy values. Everything else evaluates to `true` in `if` clauses. Depending on the application, it may be important to specify a `blank?` protocol that returns a boolean for other data types that should be considered "blank". For instance, an empty list or an empty binary could be considered blank. Such protocol could be implemented as follows: defprotocol Blank do @doc "Returns `true` if `data` is considered blank/empty" def blank?(data) end Now that the protocol is defined it can be implemented. It needs to be implemented for each Elixir type; for example: # Integers are never blank defimpl Blank, for: Integer do def blank?(number), do: false end # The only blank list is the empty one defimpl Blank, for: List do def blank?([]), do: true def blank?(_), do: false end # The only blank atoms are `false` and `nil` defimpl Blank, for: Atom do def blank?(false), do: true def blank?(nil), do: true def blank?(_), do: false end The implementation of the `Blank` protocol would need to be defined for all Elixir types. The available types are: * Structs (see below) * `Tuple` * `Atom` * `List` * `BitString` * `Integer` * `Float` * `Function` * `PID` * `Map` * `Port` * `Reference` * `Any` (see below) ## Protocols and Structs The real benefit of protocols comes when mixed with structs. For instance, Elixir ships with many data types implemented as structs, like `HashDict` and `HashSet`. We can implement the `Blank` protocol for those types as well: defimpl Blank, for: [HashDict, HashSet] do def blank?(enum_like), do: Enum.empty?(enum_like) end When implementing a protocol for a struct, the `:for` option can be omitted if the `defimpl` call is inside the module that defines the struct: defmodule User do defstruct [:email, :name] defimpl Blank do def blank?(%User{}), do: false end end If a protocol is not found for a given type, it will fallback to `Any`. ## Fallback to any In some cases, it may be convenient to provide a default implementation for all types. This can be achieved by setting the `@fallback_to_any` attribute to `true` in the protocol definition: defprotocol Blank do @fallback_to_any true def blank?(data) end The `Blank` protocol can now be implemented for `Any`: defimpl Blank, for: Any do def blank?(_), do: true end One may wonder why such behaviour (fallback to any) is not the default one. It is two-fold: first, the majority of protocols cannot implement an action in a generic way for all types; in fact, providing a default implementation may be harmful, because users may rely on the default implementation instead of providing a specialized one. Second, falling back to `Any` adds an extra lookup to all types, which is unnecessary overhead unless an implementation for `Any` is required. ## Types Defining a protocol automatically defines a type named `t`, which can be used as follows: @spec present?(Blank.t) :: boolean def present?(blank) do not Blank.blank?(blank) end The `@spec` above expresses that all types allowed to implement the given protocol are valid argument types for the given function. ## Reflection Any protocol module contains three extra functions: * `__protocol__/1` - returns the protocol name when `:name` is given, and a keyword list with the protocol functions and their arities when `:functions` is given * `impl_for/1` - receives a structure and returns the module that implements the protocol for the structure, `nil` otherwise * `impl_for!/1` - same as above but raises an error if an implementation is not found Enumerable.__protocol__(:functions) #=> [count: 1, member?: 2, reduce: 3] Enumerable.impl_for([]) #=> Enumerable.List Enumerable.impl_for(42) #=> nil ## Consolidation In order to cope with code loading in development, protocols in Elixir provide a slow implementation of protocol dispatching specific to development. In order to speed up dispatching in production environments, where all implementations are known up-front, Elixir provides a feature called protocol consolidation. For this reason, all protocols are compiled with `debug_info` set to `true`, regardless of the option set by `elixirc` compiler. The debug info though may be removed after consolidation. For more information on how to apply protocol consolidation to a given project, please check the functions in the `Protocol` module or the `mix compile.protocols` task. """ defmacro defprotocol(name, do: block) do Protocol.__protocol__(name, do: block) end @doc """ Defines an implementation for the given protocol. See `defprotocol/2` for more information and examples on protocols. Inside an implementation, the name of the protocol can be accessed via `@protocol` and the current target as `@for`. """ defmacro defimpl(name, opts, do_block \\ []) do merged = Keyword.merge(opts, do_block) merged = Keyword.put_new(merged, :for, __CALLER__.module) Protocol.__impl__(name, merged) end @doc """ Makes the given functions in the current module overridable. An overridable function is lazily defined, allowing a developer to override it. ## Example defmodule DefaultMod do defmacro __using__(_opts) do quote do def test(x, y) do x + y end defoverridable [test: 2] end end end defmodule InheritMod do use DefaultMod def test(x, y) do x * y + super(x, y) end end As seen as in the example above, `super` can be used to call the default implementation. """ defmacro defoverridable(keywords) do quote do Module.make_overridable(__MODULE__, unquote(keywords)) end end @doc """ `use` is a simple mechanism for using a given module into the current context. ## Examples For example, in order to write tests using the ExUnit framework, a developer should use the `ExUnit.Case` module: defmodule AssertionTest do use ExUnit.Case, async: true test "always pass" do assert true end end By calling `use`, a hook called `__using__` will be invoked in `ExUnit.Case` which will then do the proper setup. Simply put, `use` translates to to: defmodule AssertionTest do require ExUnit.Case ExUnit.Case.__using__([async: true]) test "always pass" do assert true end end `__using__/1` is just a regular macro that can be defined in any module: defmodule MyModule do defmacro __using__(opts) do quote do # code that will run in the module that uses MyModule end end end """ defmacro use(module, opts \\ []) do expanded = Macro.expand(module, __CALLER__) case is_atom(expanded) do false -> raise ArgumentError, "invalid arguments for use, expected an atom or alias as argument" true -> quote do require unquote(expanded) unquote(expanded).__using__(unquote(opts)) end end end @doc """ Define a function that delegates to another module. Functions defined with `defdelegate/2` are public and can be invoked from outside the module they're defined in (like if they were defined using `def/2`). When the desire is to delegate as private functions, `import` should be used. Delegation only works with functions; delegating macros is not supported. ## Options * `:to` - the expression to delegate to. Any expression is allowed and its results will be evaluated at runtime. Usually evaluates to the name of a module. * `:as` - the function to call on the target given in `:to`. This parameter is optional and defaults to the name being delegated (`funs`). * `:append_first` - if `true`, when delegated, the first argument passed to the delegated function will be relocated to the end of the arguments when dispatched to the target. The motivation behind this is because Elixir normalizes the "handle" as the first argument while some Erlang modules expect it as the last argument. ## Examples defmodule MyList do defdelegate reverse(list), to: :lists defdelegate other_reverse(list), to: :lists, as: :reverse defdelegate [reverse(list), map(list, callback)], to: :lists, append_first: true end MyList.reverse([1, 2, 3]) #=> [3, 2, 1] MyList.other_reverse([1, 2, 3]) #=> [3, 2, 1] MyList.map([1, 2, 3], &(&1 * 2)) #=> [2, 4, 6] """ defmacro defdelegate(funs, opts) do funs = Macro.escape(funs, unquote: true) quote bind_quoted: [funs: funs, opts: opts] do target = Keyword.get(opts, :to) || raise ArgumentError, "expected to: to be given as argument" for fun <- List.wrap(funs) do {name, args, as, as_args} = Kernel.Def.delegate(fun, opts) def unquote(name)(unquote_splicing(args)) do unquote(target).unquote(as)(unquote_splicing(as_args)) end end end end ## Sigils @doc ~S""" Handles the sigil `~S`. It simply returns a string without escaping characters and without interpolations. ## Examples iex> ~S(foo) "foo" iex> ~S(f#{o}o) "f\#{o}o" """ defmacro sigil_S(term, modifiers) defmacro sigil_S(string, []), do: string @doc ~S""" Handles the sigil `~s`. It returns a string as if it was a double quoted string, unescaping characters and replacing interpolations. ## Examples iex> ~s(foo) "foo" iex> ~s(f#{:o}o) "foo" iex> ~s(f\#{:o}o) "f\#{:o}o" """ defmacro sigil_s(term, modifiers) defmacro sigil_s({:<<>>, line, pieces}, []) do {:<<>>, line, Macro.unescape_tokens(pieces)} end @doc ~S""" Handles the sigil `~C`. It simply returns a char list without escaping characters and without interpolations. ## Examples iex> ~C(foo) 'foo' iex> ~C(f#{o}o) 'f\#{o}o' """ defmacro sigil_C(term, modifiers) defmacro sigil_C({:<<>>, _line, [string]}, []) when is_binary(string) do String.to_char_list(string) end @doc ~S""" Handles the sigil `~c`. It returns a char list as if it were a single quoted string, unescaping characters and replacing interpolations. ## Examples iex> ~c(foo) 'foo' iex> ~c(f#{:o}o) 'foo' iex> ~c(f\#{:o}o) 'f\#{:o}o' """ defmacro sigil_c(term, modifiers) # We can skip the runtime conversion if we are # creating a binary made solely of series of chars. defmacro sigil_c({:<<>>, _line, [string]}, []) when is_binary(string) do String.to_char_list(Macro.unescape_string(string)) end defmacro sigil_c({:<<>>, line, pieces}, []) do binary = {:<<>>, line, Macro.unescape_tokens(pieces)} quote do: String.to_char_list(unquote(binary)) end @doc """ Handles the sigil `~r`. It returns a regular expression pattern, unescaping characters and replacing interpolations. More information on regexes can be found in the `Regex` module. ## Examples iex> Regex.match?(~r(foo), "foo") true iex> Regex.match?(~r/a#{:b}c/, "abc") true """ defmacro sigil_r(term, modifiers) defmacro sigil_r({:<<>>, _line, [string]}, options) when is_binary(string) do binary = Macro.unescape_string(string, fn(x) -> Regex.unescape_map(x) end) regex = Regex.compile!(binary, :binary.list_to_bin(options)) Macro.escape(regex) end defmacro sigil_r({:<<>>, line, pieces}, options) do binary = {:<<>>, line, Macro.unescape_tokens(pieces, fn(x) -> Regex.unescape_map(x) end)} quote do: Regex.compile!(unquote(binary), unquote(:binary.list_to_bin(options))) end @doc ~S""" Handles the sigil `~R`. It returns a regular expression pattern without escaping nor interpreting interpolations. More information on regexes can be found in the `Regex` module. ## Examples iex> Regex.match?(~R(f#{1,3}o), "f#o") true """ defmacro sigil_R(term, modifiers) defmacro sigil_R({:<<>>, _line, [string]}, options) when is_binary(string) do regex = Regex.compile!(string, :binary.list_to_bin(options)) Macro.escape(regex) end @doc ~S""" Handles the sigil `~w`. It returns a list of "words" split by whitespace. Character unescaping and interpolation happens for each word. ## Modifiers * `s`: words in the list are strings (default) * `a`: words in the list are atoms * `c`: words in the list are char lists ## Examples iex> ~w(foo #{:bar} baz) ["foo", "bar", "baz"] iex> ~w(--source test/enum_test.exs) ["--source", "test/enum_test.exs"] iex> ~w(foo bar baz)a [:foo, :bar, :baz] """ defmacro sigil_w(term, modifiers) defmacro sigil_w({:<<>>, _line, [string]}, modifiers) when is_binary(string) do split_words(Macro.unescape_string(string), modifiers) end defmacro sigil_w({:<<>>, line, pieces}, modifiers) do binary = {:<<>>, line, Macro.unescape_tokens(pieces)} split_words(binary, modifiers) end @doc ~S""" Handles the sigil `~W`. It returns a list of "words" split by whitespace without escaping nor interpreting interpolations. ## Modifiers * `s`: words in the list are strings (default) * `a`: words in the list are atoms * `c`: words in the list are char lists ## Examples iex> ~W(foo #{bar} baz) ["foo", "\#{bar}", "baz"] """ defmacro sigil_W(term, modifiers) defmacro sigil_W({:<<>>, _line, [string]}, modifiers) when is_binary(string) do split_words(string, modifiers) end defp split_words("", _modifiers), do: [] defp split_words(string, modifiers) do mod = case modifiers do [] -> ?s [mod] when mod == ?s or mod == ?a or mod == ?c -> mod _else -> raise ArgumentError, "modifier must be one of: s, a, c" end case is_binary(string) do true -> case mod do ?s -> String.split(string) ?a -> for p <- String.split(string), do: String.to_atom(p) ?c -> for p <- String.split(string), do: String.to_char_list(p) end false -> case mod do ?s -> quote do: String.split(unquote(string)) ?a -> quote do: for(p <- String.split(unquote(string)), do: String.to_atom(p)) ?c -> quote do: for(p <- String.split(unquote(string)), do: String.to_char_list(p)) end end end ## Shared functions defp optimize_boolean({:case, meta, args}) do {:case, [{:optimize_boolean, true}|meta], args} end # We need this check only for bootstrap purposes. # Once Kernel is loaded and we recompile, it is a no-op. case :code.ensure_loaded(Kernel) do {:module, _} -> defp bootstraped?(_), do: true {:error, _} -> defp bootstraped?(module), do: :code.ensure_loaded(module) == {:module, module} end defp assert_module_scope(env, fun, arity) do case env.module do nil -> raise ArgumentError, "cannot invoke #{fun}/#{arity} outside module" _ -> :ok end end defp assert_no_function_scope(env, fun, arity) do case env.function do nil -> :ok _ -> raise ArgumentError, "cannot invoke #{fun}/#{arity} inside function/macro" end end defp env_stacktrace(env) do case bootstraped?(Path) do true -> Macro.Env.stacktrace(env) false -> [] end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/000077500000000000000000000000001254730255300212055ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/cli.ex000066400000000000000000000270411254730255300223160ustar00rootroot00000000000000defmodule Kernel.CLI do @moduledoc false @blank_config %{commands: [], output: ".", compile: [], halt: true, compiler_options: [], errors: [], pa: [], pz: [], verbose_compile: false} @doc """ This is the API invoked by Elixir boot process. """ def main(argv) do argv = for arg <- argv, do: IO.chardata_to_string(arg) {config, argv} = parse_argv(argv) System.argv(argv) run fn _ -> errors = process_commands(config) if errors != [] do Enum.each(errors, &IO.puts(:stderr, &1)) System.halt(1) end end, config.halt end @doc """ Runs the given function by catching any failure and printing them to stdout. `at_exit` hooks are also invoked before exiting. This function is used by Elixir's CLI and also by escripts generated by Elixir. """ def run(fun, halt \\ true) do res = exec_fun(fun, {:ok, 0}) if elem(res, 0) == :shutdown or halt do {_, int} = at_exit(res) System.halt(int) end end @doc false def parse_argv(argv) do parse_argv(argv, @blank_config) end @doc false def process_commands(config) do results = Enum.map(Enum.reverse(config.commands), &process_command(&1, config)) errors = for {:error, msg} <- results, do: msg Enum.reverse(config.errors, errors) end ## Helpers defp at_exit(res) do hooks = :elixir_config.get_and_put(:at_exit, []) res = Enum.reduce(hooks, res, &exec_fun/2) if hooks == [], do: res, else: at_exit(res) end defp exec_fun(fun, res) when is_function(fun, 1) and is_tuple(res) do parent = self() {pid, ref} = spawn_monitor fn -> try do fun.(elem(res, 1)) catch :exit, {:shutdown, int} when is_integer(int) -> send parent, {self, {:shutdown, int}} exit({:shutdown, int}) :exit, reason when reason == :normal when reason == :shutdown when tuple_size(reason) == 2 and elem(reason, 0) == :shutdown -> send parent, {self, {:shutdown, 0}} exit(reason) kind, reason -> stack = System.stacktrace print_error(kind, reason, stack) send parent, {self, {:shutdown, 1}} :erlang.raise(kind, reason, stack) else _ -> send parent, {self, res} end end receive do {^pid, res} -> :erlang.demonitor(ref, [:flush]) res {:DOWN, ^ref, _, _, other} -> print_error({:EXIT, pid}, other, []) {:shutdown, 1} end end defp shared_option?(list, config, callback) do case parse_shared(list, config) do {[h|hs], _} when h == hd(list) -> new_config = %{config | errors: ["#{h} : Unknown option" | config.errors]} callback.(hs, new_config) {new_list, new_config} -> callback.(new_list, new_config) end end defp print_error(kind, reason, trace) do IO.puts :stderr, Exception.format(kind, reason, prune_stacktrace(trace)) end @elixir_internals [:elixir, :elixir_exp, :elixir_compiler, :elixir_module, :elixir_clauses, :elixir_translator, :elixir_expand, :elixir_lexical, :elixir_exp_clauses] defp prune_stacktrace([{mod, _, _, _}|t]) when mod in @elixir_internals do prune_stacktrace(t) end defp prune_stacktrace([{__MODULE__, :wrapper, 1, _}|_]) do [] end defp prune_stacktrace([h|t]) do [h|prune_stacktrace(t)] end defp prune_stacktrace([]) do [] end # Parse shared options defp parse_shared([opt|_t], _config) when opt in ["-v", "--version"] do IO.puts "Elixir #{System.version}" System.halt 0 end defp parse_shared(["-pa", h|t], config) do paths = expand_code_path(h) Enum.each(paths, &:code.add_patha/1) parse_shared t, %{config | pa: config.pa ++ paths} end defp parse_shared(["-pz", h|t], config) do paths = expand_code_path(h) Enum.each(paths, &:code.add_pathz/1) parse_shared t, %{config | pz: config.pz ++ paths} end defp parse_shared(["--app", h|t], config) do parse_shared t, %{config | commands: [{:app, h} | config.commands]} end defp parse_shared(["--no-halt"|t], config) do parse_shared t, %{config | halt: false} end defp parse_shared(["-e", h|t], config) do parse_shared t, %{config | commands: [{:eval, h} | config.commands]} end defp parse_shared(["-r", h|t], config) do parse_shared t, %{config | commands: [{:require, h} | config.commands]} end defp parse_shared(["-pr", h|t], config) do parse_shared t, %{config | commands: [{:parallel_require, h} | config.commands]} end defp parse_shared([erl, _|t], config) when erl in ["--erl", "--sname", "--name", "--cookie"] do parse_shared t, config end defp parse_shared([erl|t], config) when erl in ["--detached", "--hidden", "--werl"] do parse_shared t, config end defp parse_shared(list, config) do {list, config} end defp expand_code_path(path) do path = Path.expand(path) case Path.wildcard(path) do [] -> [to_char_list(path)] list -> Enum.map(list, &to_char_list/1) end end # Process init options defp parse_argv(["--"|t], config) do {config, t} end defp parse_argv(["+elixirc"|t], config) do parse_compiler t, config end defp parse_argv(["+iex"|t], config) do parse_iex t, config end defp parse_argv(["-S", h|t], config) do {%{config | commands: [{:script, h} | config.commands]}, t} end defp parse_argv([h|t] = list, config) do case h do "-" <> _ -> shared_option? list, config, &parse_argv(&1, &2) _ -> if Keyword.has_key?(config.commands, :eval) do {config, list} else {%{config | commands: [{:file, h} | config.commands]}, t} end end end defp parse_argv([], config) do {config, []} end # Parse compiler options defp parse_compiler(["--"|t], config) do {config, t} end defp parse_compiler(["-o", h|t], config) do parse_compiler t, %{config | output: h} end defp parse_compiler(["--no-docs"|t], config) do parse_compiler t, %{config | compiler_options: [{:docs, false} | config.compiler_options]} end defp parse_compiler(["--no-debug-info"|t], config) do parse_compiler t, %{config | compiler_options: [{:debug_info, false} | config.compiler_options]} end defp parse_compiler(["--ignore-module-conflict"|t], config) do parse_compiler t, %{config | compiler_options: [{:ignore_module_conflict, true} | config.compiler_options]} end defp parse_compiler(["--warnings-as-errors"|t], config) do parse_compiler t, %{config | compiler_options: [{:warnings_as_errors, true} | config.compiler_options]} end defp parse_compiler(["--verbose"|t], config) do parse_compiler t, %{config | verbose_compile: true} end defp parse_compiler([h|t] = list, config) do case h do "-" <> _ -> shared_option? list, config, &parse_compiler(&1, &2) _ -> pattern = if File.dir?(h), do: "#{h}/**/*.ex", else: h parse_compiler t, %{config | compile: [pattern | config.compile]} end end defp parse_compiler([], config) do {%{config | commands: [{:compile, config.compile}|config.commands]}, []} end # Parse iex options defp parse_iex(["--"|t], config) do {config, t} end # This clause is here so that Kernel.CLI does not # error out with "unknown option" defp parse_iex(["--dot-iex", _|t], config) do parse_iex t, config end defp parse_iex([opt, _|t], config) when opt in ["--remsh"] do parse_iex t, config end defp parse_iex(["-S", h|t], config) do {%{config | commands: [{:script, h} | config.commands]}, t} end defp parse_iex([h|t] = list, config) do case h do "-" <> _ -> shared_option? list, config, &parse_iex(&1, &2) _ -> {%{config | commands: [{:file, h} | config.commands]}, t} end end defp parse_iex([], config) do {config, []} end # Process commands defp process_command({:cookie, h}, _config) do if Node.alive? do wrapper fn -> Node.set_cookie(String.to_atom(h)) end else {:error, "--cookie : Cannot set cookie if the node is not alive (set --name or --sname)"} end end defp process_command({:eval, expr}, _config) when is_binary(expr) do wrapper fn -> Code.eval_string(expr, []) end end defp process_command({:app, app}, _config) when is_binary(app) do case Application.ensure_all_started(String.to_atom(app)) do {:error, {app, reason}} -> {:error, "--app : Could not start application #{app}: " <> Application.format_error(reason)} {:ok, _} -> :ok end end defp process_command({:script, file}, _config) when is_binary(file) do if exec = find_elixir_executable(file) do wrapper fn -> Code.require_file(exec) end else {:error, "-S : Could not find executable #{file}"} end end defp process_command({:file, file}, _config) when is_binary(file) do if File.regular?(file) do wrapper fn -> Code.require_file(file) end else {:error, "No file named #{file}"} end end defp process_command({:require, pattern}, _config) when is_binary(pattern) do files = filter_patterns(pattern) if files != [] do wrapper fn -> Enum.map files, &Code.require_file(&1) end else {:error, "-r : No files matched pattern #{pattern}"} end end defp process_command({:parallel_require, pattern}, _config) when is_binary(pattern) do files = filter_patterns(pattern) if files != [] do wrapper fn -> Kernel.ParallelRequire.files(files) end else {:error, "-pr : No files matched pattern #{pattern}"} end end defp process_command({:compile, patterns}, config) do # If ensuring the dir returns an error no files will be found. _ = :filelib.ensure_dir(:filename.join(config.output, ".")) case filter_multiple_patterns(patterns) do {:ok, []} -> {:error, "No files matched provided patterns"} {:ok, files} -> wrapper fn -> Code.compiler_options(config.compiler_options) Kernel.ParallelCompiler.files_to_path(files, config.output, each_file: fn file -> if config.verbose_compile do IO.puts "Compiled #{file}" end end) end {:missing, missing} -> {:error, "No files matched pattern(s) #{Enum.join(missing, ",")}"} end end defp filter_patterns(pattern) do pattern |> Path.wildcard |> :lists.usort |> Enum.filter(&File.regular?/1) end defp filter_multiple_patterns(patterns) do matched_files = Enum.map patterns, fn(pattern) -> case filter_patterns(pattern) do [] -> {:missing, pattern} files -> {:ok, files} end end files = Enum.filter_map matched_files, fn(match) -> elem(match, 0) == :ok end, &elem(&1, 1) missing_patterns = Enum.filter_map matched_files, fn(match) -> elem(match, 0) == :missing end, &elem(&1, 1) if missing_patterns == [] do {:ok, :lists.usort(Enum.concat(files))} else {:missing, :lists.usort(missing_patterns)} end end defp wrapper(fun) do _ = fun.() :ok end defp find_elixir_executable(file) do if exec = System.find_executable(file) do # If we are on Windows, the executable is going to be # a .bat file that must be in the same directory as # the actual Elixir executable. case :os.type() do {:win32, _} -> base = Path.rootname(exec) if File.regular?(base), do: base, else: exec _ -> exec end end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/def.ex000066400000000000000000000026061254730255300223050ustar00rootroot00000000000000defmodule Kernel.Def do @moduledoc false @doc """ Callback invoked at compile time for `defdelegate`. """ def delegate(fun, opts) do append_first = Keyword.get(opts, :append_first, false) {name, args} = case Macro.decompose_call(fun) do {_, _} = pair -> pair _ -> raise ArgumentError, "invalid syntax in defdelegate #{Macro.to_string(fun)}" end as_args = case append_first and args != [] do true -> tl(args) ++ [hd(args)] false -> args end as = Keyword.get(opts, :as, name) {name, args, as, as_args} end @doc """ Callback invoked at compile time for `defstruct`. """ def struct(module, fields) do case fields do fs when is_list(fs) -> :ok other -> raise ArgumentError, "struct fields definition must be list, got: #{inspect other}" end fields = :lists.map(fn {key, val} when is_atom(key) -> try do Macro.escape(val) rescue e in [ArgumentError] -> raise ArgumentError, "invalid value for struct field #{key}, " <> Exception.message(e) else _ -> {key, val} end key when is_atom(key) -> {key, nil} other -> raise ArgumentError, "struct field names must be atoms, got: #{inspect other}" end, fields) :maps.put(:__struct__, module, :maps.from_list(fields)) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/error_handler.ex000066400000000000000000000023061254730255300243720ustar00rootroot00000000000000# Implement error_handler pattern for Erlang # which is integrated with Kernel.ParallelCompiler defmodule Kernel.ErrorHandler do @moduledoc false def undefined_function(module, fun, args) do ensure_loaded(module) :error_handler.undefined_function(module, fun, args) end def undefined_lambda(module, fun, args) do ensure_loaded(module) :error_handler.undefined_lambda(module, fun, args) end def release() do # On release, no further allow elixir_ensure_compiled # directives and revert to the original error handler. # Note we should not delete the elixir_compiler_pid though, # as we still want to send notifications to the compiler. :erlang.erase(:elixir_ensure_compiled) :erlang.process_flag(:error_handler, :error_handler) :ok end defp ensure_loaded(module) do case Code.ensure_loaded(module) do {:module, _} -> :ok {:error, _} -> parent = :erlang.get(:elixir_compiler_pid) ref = :erlang.make_ref send parent, {:waiting, :module, self(), ref, module} :erlang.garbage_collect(self) receive do {^ref, :ready} -> :ok {^ref, :release} -> release() end end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/lexical_tracker.ex000066400000000000000000000101441254730255300246770ustar00rootroot00000000000000# This is a module Elixir responsible for tracking # the usage of aliases, imports and requires in the Elixir scope. # # The implementation simply stores dispatch information in an # ETS table and then consults this table once compilation is done. # # Note that since this is required for bootstrap, we can't use # any of the `GenServer.Behaviour` conveniences. defmodule Kernel.LexicalTracker do @moduledoc false @timeout 30_000 @behaviour :gen_server @import 2 @alias 3 @doc """ Returns all remotes linked to in this lexical scope. """ def remotes(arg) do ets = :gen_server.call(to_pid(arg), :ets, @timeout) :ets.match(ets, {:"$1", :_, :_}) |> List.flatten end @doc """ Gets the destination the lexical scope is meant to compile to. """ def dest(arg) do :gen_server.call(to_pid(arg), :dest, @timeout) end defp to_pid(pid) when is_pid(pid), do: pid defp to_pid(mod) when is_atom(mod) do table = :elixir_module.data_table(mod) [{_, val}] = :ets.lookup(table, {:elixir, :lexical_tracker}) val end # Internal API # Starts the tracker and returns its pid. @doc false def start_link(dest) do :gen_server.start_link(__MODULE__, dest, []) end @doc false def stop(pid) do :gen_server.cast(pid, :stop) end @doc false def add_import(pid, module, line, warn) do :gen_server.cast(pid, {:add_import, module, line, warn}) end @doc false def add_alias(pid, module, line, warn) do :gen_server.cast(pid, {:add_alias, module, line, warn}) end @doc false def remote_dispatch(pid, module) do :gen_server.cast(pid, {:remote_dispatch, module}) end @doc false def import_dispatch(pid, module) do :gen_server.cast(pid, {:import_dispatch, module}) end @doc false def alias_dispatch(pid, module) do :gen_server.cast(pid, {:alias_dispatch, module}) end @doc false def collect_unused_imports(pid) do unused(pid, @import) end @doc false def collect_unused_aliases(pid) do unused(pid, @alias) end defp unused(pid, pos) do ets = :gen_server.call(pid, :ets, @timeout) :ets.foldl(fn {module, _, _} = tuple, acc when is_integer(:erlang.element(pos, tuple)) -> [{module, :erlang.element(pos, tuple)}|acc] _, acc -> acc end, [], ets) |> Enum.sort end # Callbacks def init(dest) do {:ok, {:ets.new(:lexical, [:protected]), dest}} end @doc false def handle_call(:ets, _from, {d, dest}) do {:reply, d, {d, dest}} end def handle_call(:dest, _from, {d, dest}) do {:reply, dest, {d, dest}} end def handle_cast({:remote_dispatch, module}, {d, dest}) do add_module(d, module) {:noreply, {d, dest}} end def handle_cast({:import_dispatch, module}, {d, dest}) do add_dispatch(d, module, @import) {:noreply, {d, dest}} end def handle_cast({:alias_dispatch, module}, {d, dest}) do add_dispatch(d, module, @alias) {:noreply, {d, dest}} end def handle_cast({:add_import, module, line, warn}, {d, dest}) do add_directive(d, module, line, warn, @import) {:noreply, {d, dest}} end def handle_cast({:add_alias, module, line, warn}, {d, dest}) do add_directive(d, module, line, warn, @alias) {:noreply, {d, dest}} end def handle_cast(:stop, {d, dest}) do {:stop, :normal, {d, dest}} end @doc false def handle_info(_msg, {d, dest}) do {:noreply, {d, dest}} end @doc false def terminate(_reason, _state) do :ok end @doc false def code_change(_old, state, _extra) do {:ok, state} end # Callbacks helpers # In the table we keep imports and aliases. # If the value is false, it was not imported/aliased # If the value is true, it was imported/aliased # If the value is a line, it was imported/aliased and has a pending warning defp add_module(d, module) do :ets.insert_new(d, {module, false, false}) end defp add_dispatch(d, module, pos) do :ets.update_element(d, module, {pos, true}) end defp add_directive(d, module, line, warn, pos) do add_module(d, module) marker = if warn, do: line, else: true :ets.update_element(d, module, {pos, marker}) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/parallel_compiler.ex000066400000000000000000000222571254730255300252410ustar00rootroot00000000000000defmodule Kernel.ParallelCompiler do @moduledoc """ A module responsible for compiling files in parallel. """ @doc """ Compiles the given files. Those files are compiled in parallel and can automatically detect dependencies between them. Once a dependency is found, the current file stops being compiled until the dependency is resolved. If there is an error during compilation or if `warnings_as_errors` is set to `true` and there is a warning, this function will fail with an exception. This function accepts the following options: * `:each_file` - for each file compiled, invokes the callback passing the file * `:each_module` - for each module compiled, invokes the callback passing the file, module and the module bytecode * `:dest` - the destination directory for the beam files. When using `files/2`, this information is only used to properly annotate the beam files before they are loaded into memory. If you want a file to actually be written to `dest`, use `files_to_path/3` instead. Returns the modules generated by each compiled file. """ def files(files, options \\ []) def files(files, options) when is_list(options) do spawn_compilers(files, nil, options) end @doc """ Compiles the given files to the given path. Read `files/2` for more information. """ def files_to_path(files, path, options \\ []) def files_to_path(files, path, options) when is_binary(path) and is_list(options) do spawn_compilers(files, path, options) end defp spawn_compilers(files, path, options) do true = Code.ensure_loaded?(Kernel.ErrorHandler) compiler_pid = self() :elixir_code_server.cast({:reset_warnings, compiler_pid}) schedulers = max(:erlang.system_info(:schedulers_online), 2) result = spawn_compilers(files, files, path, options, [], [], schedulers, []) # In case --warning-as-errors is enabled and there was a warning, # compilation status will be set to error and we fail with CompileError case :elixir_code_server.call({:compilation_status, compiler_pid}) do :ok -> result :error -> IO.puts :stderr, "Compilation failed due to warnings while using the --warnings-as-errors option" exit({:shutdown, 1}) end end # We already have 4 currently running, don't spawn new ones defp spawn_compilers(entries, original, output, options, waiting, queued, schedulers, result) when length(queued) - length(waiting) >= schedulers do wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result) end # Release waiting processes defp spawn_compilers([h|t], original, output, options, waiting, queued, schedulers, result) when is_pid(h) do {_kind, ^h, ref, _module} = List.keyfind(waiting, h, 1) send h, {ref, :ready} waiting = List.keydelete(waiting, h, 1) spawn_compilers(t, original, output, options, waiting, queued, schedulers, result) end # Spawn a compiler for each file in the list until we reach the limit defp spawn_compilers([h|t], original, output, options, waiting, queued, schedulers, result) do parent = self() {pid, ref} = :erlang.spawn_monitor fn -> # Notify Code.ensure_compiled/2 that we should # attempt to compile the module by doing a dispatch. :erlang.put(:elixir_ensure_compiled, true) # Set the elixir_compiler_pid used by our custom Kernel.ErrorHandler. :erlang.put(:elixir_compiler_pid, parent) :erlang.process_flag(:error_handler, Kernel.ErrorHandler) exit(try do _ = if output do :elixir_compiler.file_to_path(h, output) else :elixir_compiler.file(h, Keyword.get(options, :dest)) end {:shutdown, h} catch kind, reason -> {:failure, kind, reason, System.stacktrace} end) end spawn_compilers(t, original, output, options, waiting, [{pid, ref, h}|queued], schedulers, result) end # No more files, nothing waiting, queue is empty, we are done defp spawn_compilers([], _original, _output, _options, [], [], _schedulers, result) do for {:module, mod} <- result, do: mod end # Queued x, waiting for x: POSSIBLE ERROR! Release processes so we get the failures defp spawn_compilers([], original, output, options, waiting, queued, schedulers, result) when length(waiting) == length(queued) do Enum.each queued, fn {child, _, _} -> {_kind, ^child, ref, _module} = List.keyfind(waiting, child, 1) send child, {ref, :release} end wait_for_messages([], original, output, options, waiting, queued, schedulers, result) end # No more files, but queue and waiting are not full or do not match defp spawn_compilers([], original, output, options, waiting, queued, schedulers, result) do wait_for_messages([], original, output, options, waiting, queued, schedulers, result) end # Wait for messages from child processes defp wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result) do receive do {:struct_available, module} -> available = for {:struct, pid, _, waiting_module} <- waiting, module == waiting_module, not pid in entries, do: pid spawn_compilers(available ++ entries, original, output, options, waiting, queued, schedulers, [{:struct, module}|result]) {:module_available, child, ref, file, module, binary} -> if callback = Keyword.get(options, :each_module) do callback.(file, module, binary) end # Release the module loader which is waiting for an ack send child, {ref, :ack} available = for {_kind, pid, _, waiting_module} <- waiting, module == waiting_module, not pid in entries, do: pid spawn_compilers(available ++ entries, original, output, options, waiting, queued, schedulers, [{:module, module}|result]) {:waiting, kind, child, ref, on} -> defined = fn {k, m} -> on == m and k in [kind, :module] end # Oops, we already got it, do not put it on waiting. if :lists.any(defined, result) do send child, {ref, :ready} else waiting = [{kind, child, ref, on}|waiting] end spawn_compilers(entries, original, output, options, waiting, queued, schedulers, result) {:DOWN, _down_ref, :process, down_pid, {:shutdown, file}} -> if callback = Keyword.get(options, :each_file) do callback.(file) end # Sometimes we may have spurious entries in the waiting # list because someone invoked try/rescue UndefinedFunctionError new_entries = List.delete(entries, down_pid) new_queued = List.keydelete(queued, down_pid, 0) new_waiting = List.keydelete(waiting, down_pid, 1) spawn_compilers(new_entries, original, output, options, new_waiting, new_queued, schedulers, result) {:DOWN, down_ref, :process, _down_pid, reason} -> handle_failure(down_ref, reason, entries, waiting, queued) wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result) end end defp handle_failure(ref, reason, entries, waiting, queued) do if file = find_failure(ref, queued) do print_failure(file, reason) if all_missing?(entries, waiting, queued) do collect_failures(queued, length(queued) - 1) end Enum.each queued, fn {child, _, _} -> Process.exit(child, :kill) end exit({:shutdown, 1}) end end defp find_failure(ref, queued) do case List.keyfind(queued, ref, 1) do {_child, ^ref, file} -> file _ -> nil end end defp print_failure(_file, {:shutdown, _}) do :ok end defp print_failure(file, {:failure, kind, reason, stacktrace}) do IO.puts "\n== Compilation error on file #{Path.relative_to_cwd(file)} ==" IO.puts Exception.format(kind, reason, prune_stacktrace(stacktrace)) end defp print_failure(file, reason) do IO.puts "\n== Compilation error on file #{Path.relative_to_cwd(file)} ==" IO.puts Exception.format(:exit, reason, []) end @elixir_internals [:elixir, :elixir_exp, :elixir_compiler, :elixir_module, :elixir_translator, :elixir_expand, :elixir_lexical] defp prune_stacktrace([{mod, _, _, _}|t]) when mod in @elixir_internals do prune_stacktrace(t) end defp prune_stacktrace([h|t]) do [h|prune_stacktrace(t)] end defp prune_stacktrace([]) do [] end defp all_missing?(entries, waiting, queued) do entries == [] and waiting != [] and length(waiting) == length(queued) end defp collect_failures(_queued, 0), do: :ok defp collect_failures(queued, remaining) do receive do {:DOWN, down_ref, :process, _down_pid, reason} -> if file = find_failure(down_ref, queued) do print_failure(file, reason) collect_failures(queued, remaining - 1) else collect_failures(queued, remaining) end after # Give up if no failure appears in 5 seconds 5000 -> :ok end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/parallel_require.ex000066400000000000000000000047271254730255300251050ustar00rootroot00000000000000defmodule Kernel.ParallelRequire do @moduledoc """ A module responsible for requiring files in parallel. """ defmacrop default_callback, do: quote(do: fn x -> x end) @doc """ Requires the given files. A callback that is invoked every time a file is required can be optionally given as argument. Returns the modules generated by each required file. """ def files(files, callback \\ default_callback) do schedulers = max(:erlang.system_info(:schedulers_online), 2) spawn_requires(files, [], callback, schedulers, []) end defp spawn_requires([], [], _callback, _schedulers, result), do: result defp spawn_requires([], waiting, callback, schedulers, result) do wait_for_messages([], waiting, callback, schedulers, result) end defp spawn_requires(files, waiting, callback, schedulers, result) when length(waiting) >= schedulers do wait_for_messages(files, waiting, callback, schedulers, result) end defp spawn_requires([h|t], waiting, callback, schedulers, result) do parent = self compiler_pid = :erlang.get(:elixir_compiler_pid) ensure_compiled = :erlang.get(:elixir_ensure_compiled) {:error_handler, handler} = :erlang.process_info(parent, :error_handler) {pid, ref} = :erlang.spawn_monitor fn -> if compiler_pid != :undefined do :erlang.put(:elixir_compiler_pid, compiler_pid) end if ensure_compiled != :undefined do :erlang.put(:elixir_ensure_compiled, ensure_compiled) end :erlang.process_flag(:error_handler, handler) exit(try do new = Code.require_file(h) || [] {:required, Enum.map(new, &elem(&1, 0)), h} catch kind, reason -> {:failure, kind, reason, System.stacktrace} end) end spawn_requires(t, [{pid, ref}|waiting], callback, schedulers, result) end defp wait_for_messages(files, waiting, callback, schedulers, result) do receive do {:DOWN, ref, :process, pid, status} -> tuple = {pid, ref} if tuple in waiting do case status do {:required, mods, file} -> callback.(file) result = mods ++ result waiting = List.delete(waiting, tuple) {:failure, kind, reason, stacktrace} -> :erlang.raise(kind, reason, stacktrace) other -> :erlang.raise(:exit, other, []) end end spawn_requires(files, waiting, callback, schedulers, result) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/special_forms.ex000066400000000000000000001354751254730255300244100ustar00rootroot00000000000000defmodule Kernel.SpecialForms do @moduledoc """ In this module we define Elixir special forms. Special forms cannot be overridden by the developer and are the basic building blocks of Elixir code. Some of those forms are lexical (like `alias`, `case`, etc). The macros `{}` and `<<>>` are also special forms used to define tuple and binary data structures respectively. This module also documents Elixir's pseudo variables (`__ENV__`, `__MODULE__`, `__DIR__` and `__CALLER__`). Pseudo variables return information about Elixir's compilation environment and can only be read, never assigned to. Finally, it also documents 2 special forms, `__block__` and `__aliases__`, which are not intended to be called directly by the developer but they appear in quoted contents since they are essential in Elixir's constructs. """ @doc """ Creates a tuple. Only two item tuples are considered literals in Elixir. Therefore all other tuples are represented in the AST as a call to the special form `:{}`. Conveniences for manipulating tuples can be found in the `Tuple` module. Some functions for working with tuples are also available in `Kernel`, namely `Kernel.elem/2`, `Kernel.put_elem/3` and `Kernel.tuple_size/1`. ## Examples iex> {1, 2, 3} {1, 2, 3} iex> quote do: {1, 2, 3} {:{}, [], [1, 2, 3]} """ defmacro unquote(:{})(args) @doc """ Creates a map. Maps are key-value stores where keys are compared using the match operator (`===`). Maps can be created with the `%{}` special form where keys are associated via `=>`: %{1 => 2} Maps also support the keyword notation, as other special forms, as long as they are at the end of the argument list: %{hello: :world, with: :keywords} %{:hello => :world, with: :keywords} If a map has duplicated keys, the last key will always have higher precedence: iex> %{a: :b, a: :c} %{a: :c} Conveniences for manipulating maps can be found in the `Map` module. ## Access syntax Besides the access functions available in the `Map` module, like `Map.get/3` and `Map.fetch/2`, a map can be accessed using the `.` operator: iex> map = %{a: :b} iex> map.a :b Note that the `.` operator expects the field to exist in the map. If not, an `ArgumentError` is raised. ## Update syntax Maps also support an update syntax: iex> map = %{:a => :b} iex> %{map | :a => :c} %{:a => :c} Notice the update syntax requires the given keys to exist. Trying to update a key that does not exist will raise an `ArgumentError`. ## AST representation Regardless if `=>` or the keywords syntax is used, Maps are always represented internally as a list of two-items tuples for simplicity: iex> quote do: %{:a => :b, c: :d} {:%{}, [], [{:a, :b}, {:c, :d}]} """ defmacro unquote(:%{})(args) @doc """ Creates a struct. A struct is a tagged map that allows developers to provide default values for keys, tags to be used in polymorphic dispatches and compile time assertions. To define a struct, you just need to implement the `__struct__/0` function in a module: defmodule User do def __struct__ do %{name: "john", age: 27} end end In practice though, structs are usually defined with the `Kernel.defstruct/1` macro: defmodule User do defstruct name: "john", age: 27 end Now a struct can be created as follows: %User{} Underneath a struct is just a map with a `__struct__` field pointing to the `User` module: %User{} == %{__struct__: User, name: "john", age: 27} A struct also validates that the given keys are part of the defined struct. The example below will fail because there is no key `:full_name` in the `User` struct: %User{full_name: "john doe"} Note that a struct specifies a minimum set of keys required for operations. Other keys can be added to structs via the regular map operations: user = %User{} Map.put(user, :a_non_struct_key, :value) An update operation specific for structs is also available: %User{user | age: 28} The syntax above will guarantee the given keys are valid at compilation time and it will guarantee at runtime the given argument is a struct, failing with `BadStructError` otherwise. Although structs are maps, by default structs do not implement any of the protocols implemented for maps. Check `Kernel.defprotocol/2` for more information on how structs can be used with protocols for polymorphic dispatch. Also see `Kernel.struct/2` for examples on how to create and update structs dynamically. """ defmacro unquote(:%)(struct, map) @doc """ Defines a new bitstring. ## Examples iex> << 1, 2, 3 >> << 1, 2, 3 >> ## Types A bitstring is made of many segments and each segment has a type. There are 9 types used in bitstrings: - `integer` - `float` - `bits` (alias for bitstring) - `bitstring` - `binary` - `bytes` (alias for binary) - `utf8` - `utf16` - `utf32` When no type is specified, the default is `integer`: iex> <<1, 2, 3>> <<1, 2, 3>> Elixir also accepts by default the segment to be a literal string or a literal char list, which are by expanded to integers: iex> <<0, "foo">> <<0, 102, 111, 111>> Variables or any other type need to be explicitly tagged: iex> rest = "oo" iex> <<102, rest>> ** (ArgumentError) argument error We can solve this by explicitly tagging it as a binary: iex> rest = "oo" iex> <<102, rest :: binary>> "foo" The utf8, utf16, and utf32 types are for unicode codepoints. They can also be applied to literal strings and char lists: iex> <<"foo" :: utf16>> <<0, 102, 0, 111, 0, 111>> iex> <<"foo" :: utf32>> <<0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 0, 111>> ## Options Many options can be given by using `-` as separator. Order is arbitrary, so the following are all equivalent: <<102 :: integer-native, rest :: binary>> <<102 :: native-integer, rest :: binary>> <<102 :: unsigned-big-integer, rest :: binary>> <<102 :: unsigned-big-integer-size(8), rest :: binary>> <<102 :: unsigned-big-integer-8, rest :: binary>> <<102 :: 8-integer-big-unsigned, rest :: binary>> <<102, rest :: binary>> ### Unit and Size The length of the match is equal to the `unit` (a number of bits) times the `size` (the number of repeated segnments of length `unit`). Type | Default Unit --------- | ------------ `integer` | 1 bit `float` | 1 bit `binary` | 8 bits Sizes for types are a bit more nuanced. The default size for integers is 8. For floats, it is 64. For floats, `size * unit` must result in 32 or 64, corresponding to [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point) binary32 and binary64, respectively. For binaries, the default is the size of the binary. Only the last binary in a match can use the default size. All others must have their size specified explicitly, even if the match is unambiguous. For example: iex> <> = <<"Frank the Walrus">> "Frank the Walrus" iex> {name, species} {"Frank", "Walrus"} Failing to specify the size for the non-last causes compilation to fail: <> = <<"Frank the Walrus">> ** (CompileError): a binary field without size is only allowed at the end of a binary pattern #### Shortcut Syntax Size and unit can also be specified using a syntax shortcut when passing integer values: iex> x = 1 iex> << x :: 8 >> == << x :: size(8) >> true iex> << x :: 8 * 4 >> == << x :: size(8)-unit(4) >> true This syntax reflects the fact the effective size is given by multiplying the size by the unit. ### Modifiers Some types have associated modifiers to clear up ambiguity in byte representation. Modifier | Relevant Type(s) -------------------- | ---------------- `signed` | `integer` `unsigned` (default) | `integer` `little` | `integer`, `utf16`, `utf32` `big` (default) | `integer`, `utf16`, `utf32` `native` | `integer`, `utf16`, `utf32` ### Sign Integers can be `signed` or `unsigned`, defaulting to `unsigned`. iex> <> = <<-100>> <<156>> iex> int 156 iex> <> = <<-100>> <<156>> iex> int -100 `signed` and `unsigned` are only used for matching binaries (see below) and are only used for integers. iex> <<-100 :: signed, _rest :: binary>> = <<-100, "foo">> <<156, 102, 111, 111>> ### Endianness Elixir has three options for endianness: `big`, `little`, and `native`. The default is `big`: iex> <> = <<0, 1>> <<0, 1>> iex> number 256 iex> <> = <<0, 1>> <<0, 1>> iex> number 1 `native` is determined by the VM at startup and will depend on the host operating system. ## Binary/Bitstring Matching Binary matching is a powerful feature in Elixir that is useful for extracting information from binaries as well as pattern matching. Binary matching can be used by itself to extract information from binaries: iex> <<"Hello, ", place::binary>> = "Hello, World" "Hello, World" iex> place "World" Or as a part of function definitions to pattern match: defmodule ImageTyper @png_signature <<137::size(8), 80::size(8), 78::size(8), 71::size(8), 13::size(8), 10::size(8), 26::size(8), 10::size(8)>> @jpg_signature <<255::size(8), 216::size(8)>> def type(<<@png_signature, rest::binary>>), do: :png def type(<<@jpg_signature, rest::binary>>), do: :jpg def type(_), do :unknown end ### Performance & Optimizations The Erlang compiler can provide a number of optimizations on binary creation and matching. To see optimization output, set the `bin_opt_info` compiler option: ERL_COMPILER_OPTIONS=bin_opt_info mix compile To learn more about specific optimizations and performance considerations, check out [Erlang's Efficiency Guide on handling binaries](http://www.erlang.org/doc/efficiency_guide/binaryhandling.html). """ defmacro unquote(:<<>>)(args) @doc """ Defines a remote call or an alias. The dot (`.`) in Elixir can be used for remote calls: iex> String.downcase("FOO") "foo" In this example above, we have used `.` to invoke `downcase` in the `String` alias, passing "FOO" as argument. We can also use the dot for creating aliases: iex> Hello.World Hello.World This time, we have joined two aliases, defining the final alias `Hello.World`. ## Syntax The right side of `.` may be a word starting in upcase, which represents an alias, a word starting with lowercase or underscore, any valid language operator or any name wrapped in single- or double-quotes. Those are all valid examples: iex> Kernel.Sample Kernel.Sample iex> Kernel.length([1, 2, 3]) 3 iex> Kernel.+(1, 2) 3 iex> Kernel."length"([1, 2, 3]) 3 iex> Kernel.'+'(1, 2) 3 Note that `Kernel."HELLO"` will be treated as a remote call and not an alias. This choice was done so every time single- or double-quotes are used, we have a remote call regardless of the quote contents. This decision is also reflected in the quoted expressions discussed below. ## Quoted expression When `.` is used, the quoted expression may take two distinct forms. When the right side starts with a lowercase letter (or underscore): iex> quote do: String.downcase("FOO") {{:., [], [{:__aliases__, [alias: false], [:String]}, :downcase]}, [], ["FOO"]} Notice we have an inner tuple, containing the atom `:.` representing the dot as first element: {:., [], [{:__aliases__, [alias: false], [:String]}, :downcase]} This tuple follows the general quoted expression structure in Elixir, with the name as first argument, some keyword list as metadata as second, and the number of arguments as third. In this case, the arguments is the alias `String` and the atom `:downcase`. The second argument is **always** an atom: iex> quote do: String."downcase"("FOO") {{:., [], [{:__aliases__, [alias: false], [:String]}, :downcase]}, [], ["FOO"]} The tuple containing `:.` is wrapped in another tuple, which actually represents the function call, and has `"FOO"` as argument. When the right side is an alias (i.e. starts with uppercase), we get instead: iex> quote do: Hello.World {:__aliases__, [alias: false], [:Hello, :World]} We got into more details about aliases in the `__aliases__` special form documentation. ## Unquoting We can also use unquote to generate a remote call in a quoted expression: iex> x = :downcase iex> quote do: String.unquote(x)("FOO") {{:., [], [{:__aliases__, [alias: false], [:String]}, :downcase]}, [], ["FOO"]} Similar to `Kernel."HELLO"`, `unquote(x)` will always generate a remote call, independent of the value of `x`. To generate an alias via the quoted expression, one needs to rely on `Module.concat/2`: iex> x = Sample iex> quote do: Module.concat(String, unquote(x)) {{:., [], [{:__aliases__, [alias: false], [:Module]}, :concat]}, [], [{:__aliases__, [alias: false], [:String]}, Sample]} """ defmacro unquote(:.)(left, right) @doc """ `alias` is used to setup aliases, often useful with modules names. ## Examples `alias` can be used to setup an alias for any module: defmodule Math do alias MyKeyword, as: Keyword end In the example above, we have set up `MyKeyword` to be aliased as `Keyword`. So now, any reference to `Keyword` will be automatically replaced by `MyKeyword`. In case one wants to access the original `Keyword`, it can be done by accessing `Elixir`: Keyword.values #=> uses MyKeyword.values Elixir.Keyword.values #=> uses Keyword.values Notice that calling `alias` without the `as:` option automatically sets an alias based on the last part of the module. For example: alias Foo.Bar.Baz Is the same as: alias Foo.Bar.Baz, as: Baz ## Lexical scope `import`, `require` and `alias` are called directives and all have lexical scope. This means you can set up aliases inside specific functions and it won't affect the overall scope. ## Warnings If you alias a module and you don't use the alias, Elixir is going to issue a warning implying the alias is not being used. In case the alias is generated automatically by a macro, Elixir won't emit any warnings though, since the alias was not explicitly defined. Both warning behaviours could be changed by explicitly setting the `:warn` option to `true` or `false`. """ defmacro alias(module, opts) @doc """ Requires a given module to be compiled and loaded. ## Examples Notice that usually modules should not be required before usage, the only exception is if you want to use the macros from a module. In such cases, you need to explicitly require them. Let's suppose you created your own `if` implementation in the module `MyMacros`. If you want to invoke it, you need to first explicitly require the `MyMacros`: defmodule Math do require MyMacros MyMacros.if do_something, it_works end An attempt to call a macro that was not loaded will raise an error. ## Alias shortcut `require` also accepts `as:` as an option so it automatically sets up an alias. Please check `alias` for more information. """ defmacro require(module, opts) @doc """ Imports function and macros from other modules. `import` allows one to easily access functions or macros from others modules without using the qualified name. ## Examples If you are using several functions from a given module, you can import those functions and reference them as local functions, for example: iex> import List iex> flatten([1, [2], 3]) [1, 2, 3] ## Selector By default, Elixir imports functions and macros from the given module, except the ones starting with underscore (which are usually callbacks): import List A developer can filter to import only macros or functions via the only option: import List, only: :functions import List, only: :macros Alternatively, Elixir allows a developer to pass pairs of name/arities to `:only` or `:except` as a fine grained control on what to import (or not): import List, only: [flatten: 1] import String, except: [split: 2] Notice that calling `except` for a previously declared `import` simply filters the previously imported elements. For example: import List, only: [flatten: 1, keyfind: 3] import List, except: [flatten: 1] After the two import calls above, only `List.keyfind/3` will be imported. ## Lexical scope It is important to notice that `import` is lexical. This means you can import specific macros inside specific functions: defmodule Math do def some_function do # 1) Disable `if/2` from Kernel import Kernel, except: [if: 2] # 2) Require the new `if` macro from MyMacros import MyMacros # 3) Use the new macro if do_something, it_works end end In the example above, we imported macros from `MyMacros`, replacing the original `if/2` implementation by our own within that specific function. All other functions in that module will still be able to use the original one. ## Warnings If you import a module and you don't use any of the imported functions or macros from this module, Elixir is going to issue a warning implying the import is not being used. In case the import is generated automatically by a macro, Elixir won't emit any warnings though, since the import was not explicitly defined. Both warning behaviours could be changed by explicitly setting the `:warn` option to `true` or `false`. ## Ambiguous function/macro names If two modules `A` and `B` are imported and they both contain a `foo` function with an arity of `1`, an error is only emitted if an ambiguous call to `foo/1` is actually made; that is, the errors are emitted lazily, not eagerly. """ defmacro import(module, opts) @doc """ Returns the current environment information as a `Macro.Env` struct. In the environment you can access the current filename, line numbers, set up aliases, the current function and others. """ defmacro __ENV__ @doc """ Returns the current module name as an atom or `nil` otherwise. Although the module can be accessed in the `__ENV__`, this macro is a convenient shortcut. """ defmacro __MODULE__ @doc """ Returns the current directory as a binary. Although the directory can be accessed as `Path.dirname(__ENV__.file)`, this macro is a convenient shortcut. """ defmacro __DIR__ @doc """ Returns the current calling environment as a `Macro.Env` struct. In the environment you can access the filename, line numbers, set up aliases, the function and others. """ defmacro __CALLER__ @doc """ Accesses an already bound variable in match clauses. ## Examples Elixir allows variables to be rebound via static single assignment: iex> x = 1 iex> x = x + 1 iex> x 2 However, in some situations, it is useful to match against an existing value, instead of rebinding. This can be done with the `^` special form: iex> x = 1 iex> ^x = List.first([1]) iex> ^x = List.first([2]) ** (MatchError) no match of right hand side value: 2 Note that `^` always refers to the value of x prior to the match. The following example will match: iex> x = 0 iex> {x, ^x} = {1, 0} iex> x 1 """ defmacro ^(var) @doc """ Matches the value on the right against the pattern on the left. """ defmacro left = right @doc """ Used by types and bitstrings to specify types. This operator is used in two distinct occasions in Elixir. It is used in typespecs to specify the type of a variable, function or of a type itself: @type number :: integer | float @spec add(number, number) :: number It may also be used in bit strings to specify the type of a given bit segment: <> = bits Read the documentation for `Kernel.Typespec` and `<<>>/1` for more information on typespecs and bitstrings respectively. """ defmacro left :: right @doc ~S""" Gets the representation of any expression. ## Examples quote do: sum(1, 2, 3) #=> {:sum, [], [1, 2, 3]} ## Explanation Any Elixir code can be represented using Elixir data structures. The building block of Elixir macros is a tuple with three elements, for example: {:sum, [], [1, 2, 3]} The tuple above represents a function call to `sum` passing 1, 2 and 3 as arguments. The tuple elements are: * The first element of the tuple is always an atom or another tuple in the same representation. * The second element of the tuple represents metadata. * The third element of the tuple are the arguments for the function call. The third argument may be an atom, which is usually a variable (or a local call). ## Options * `:unquote` - when `false`, disables unquoting. Useful when you have a quote inside another quote and want to control what quote is able to unquote. * `:location` - when set to `:keep`, keeps the current line and file from quote. Read the Stacktrace information section below for more information. * `:context` - sets the resolution context. * `:bind_quoted` - passes a binding to the macro. Whenever a binding is given, `unquote` is automatically disabled. ## Quote literals Besides the tuple described above, Elixir has a few literals that when quoted return themselves. They are: :sum #=> Atoms 1 #=> Integers 2.0 #=> Floats [1, 2] #=> Lists "strings" #=> Strings {key, value} #=> Tuples with two elements ## Quote and macros `quote` is commonly used with macros for code generation. As an exercise, let's define a macro that multiplies a number by itself (squared). Note there is no reason to define such as a macro (and it would actually be seen as a bad practice), but it is simple enough that it allows us to focus on the important aspects of quotes and macros: defmodule Math do defmacro squared(x) do quote do unquote(x) * unquote(x) end end end We can invoke it as: import Math IO.puts "Got #{squared(5)}" At first, there is nothing in this example that actually reveals it is a macro. But what is happening is that, at compilation time, `squared(5)` becomes `5 * 5`. The argument `5` is duplicated in the produced code, we can see this behaviour in practice though because our macro actually has a bug: import Math my_number = fn -> IO.puts "Returning 5" 5 end IO.puts "Got #{squared(my_number.())}" The example above will print: Returning 5 Returning 5 25 Notice how "Returning 5" was printed twice, instead of just once. This is because a macro receives an expression and not a value (which is what we would expect in a regular function). This means that: squared(my_number.()) Actually expands to: my_number.() * my_number.() Which invokes the function twice, explaining why we get the printed value twice! In the majority of the cases, this is actually unexpected behaviour, and that's why one of the first things you need to keep in mind when it comes to macros is to **not unquote the same value more than once**. Let's fix our macro: defmodule Math do defmacro squared(x) do quote do x = unquote(x) x * x end end end Now invoking `square(my_number.())` as before will print the value just once. In fact, this pattern is so common that most of the times you will want to use the `bind_quoted` option with `quote`: defmodule Math do defmacro squared(x) do quote bind_quoted: [x: x] do x * x end end end `:bind_quoted` will translate to the same code as the example above. `:bind_quoted` can be used in many cases and is seen as good practice, not only because it helps us from running into common mistakes but also because it allows us to leverage other tools exposed by macros, such as unquote fragments discussed in some sections below. Before we finish this brief introduction, you will notice that, even though we defined a variable `x` inside our quote: quote do x = unquote(x) x * x end When we call: import Math squared(5) x #=> ** (RuntimeError) undefined function or variable: x We can see that `x` did not leak to the user context. This happens because Elixir macros are hygienic, a topic we will discuss at length in the next sections as well. ## Hygiene in variables Consider the following example: defmodule Hygiene do defmacro no_interference do quote do: a = 1 end end require Hygiene a = 10 Hygiene.no_interference a #=> 10 In the example above, `a` returns 10 even if the macro is apparently setting it to 1 because variables defined in the macro does not affect the context the macro is executed in. If you want to set or get a variable in the caller's context, you can do it with the help of the `var!` macro: defmodule NoHygiene do defmacro interference do quote do: var!(a) = 1 end end require NoHygiene a = 10 NoHygiene.interference a #=> 1 Note that you cannot even access variables defined in the same module unless you explicitly give it a context: defmodule Hygiene do defmacro write do quote do a = 1 end end defmacro read do quote do a end end end Hygiene.write Hygiene.read #=> ** (RuntimeError) undefined function or variable: a For such, you can explicitly pass the current module scope as argument: defmodule ContextHygiene do defmacro write do quote do var!(a, ContextHygiene) = 1 end end defmacro read do quote do var!(a, ContextHygiene) end end end ContextHygiene.write ContextHygiene.read #=> 1 ## Hygiene in aliases Aliases inside quote are hygienic by default. Consider the following example: defmodule Hygiene do alias HashDict, as: D defmacro no_interference do quote do: D.new end end require Hygiene Hygiene.no_interference #=> #HashDict<[]> Notice that, even though the alias `D` is not available in the context the macro is expanded, the code above works because `D` still expands to `HashDict`. Similarly, even if we defined an alias with the same name before invoking a macro, it won't affect the macro's result: defmodule Hygiene do alias HashDict, as: D defmacro no_interference do quote do: D.new end end require Hygiene alias SomethingElse, as: D Hygiene.no_interference #=> #HashDict<[]> In some cases, you want to access an alias or a module defined in the caller. For such, you can use the `alias!` macro: defmodule Hygiene do # This will expand to Elixir.Nested.hello defmacro no_interference do quote do: Nested.hello end # This will expand to Nested.hello for # whatever is Nested in the caller defmacro interference do quote do: alias!(Nested).hello end end defmodule Parent do defmodule Nested do def hello, do: "world" end require Hygiene Hygiene.no_interference #=> ** (UndefinedFunctionError) ... Hygiene.interference #=> "world" end ## Hygiene in imports Similar to aliases, imports in Elixir are hygienic. Consider the following code: defmodule Hygiene do defmacrop get_size do quote do size("hello") end end def return_size do import Kernel, except: [size: 1] get_size end end Hygiene.return_size #=> 5 Notice how `return_size` returns 5 even though the `size/1` function is not imported. In fact, even if `return_size` imported a function from another module, it wouldn't affect the function result: def return_size do import Dict, only: [size: 1] get_size end Calling this new `return_size` will still return 5 as result. Elixir is smart enough to delay the resolution to the latest moment possible. So, if you call `size("hello")` inside quote, but no `size/1` function is available, it is then expanded in the caller: defmodule Lazy do defmacrop get_size do import Kernel, except: [size: 1] quote do size([a: 1, b: 2]) end end def return_size do import Kernel, except: [size: 1] import Dict, only: [size: 1] get_size end end Lazy.return_size #=> 2 ## Stacktrace information When defining functions via macros, developers have the option of choosing if runtime errors will be reported from the caller or from inside the quote. Let's see an example: # adder.ex defmodule Adder do @doc "Defines a function that adds two numbers" defmacro defadd do quote location: :keep do def add(a, b), do: a + b end end end # sample.ex defmodule Sample do import Adder defadd end When using `location: :keep` and invalid arguments are given to `Sample.add/2`, the stacktrace information will point to the file and line inside the quote. Without `location: :keep`, the error is reported to where `defadd` was invoked. Note `location: :keep` affects only definitions inside the quote. ## Binding and unquote fragments Elixir quote/unquote mechanisms provides a functionality called unquote fragments. Unquote fragments provide an easy way to generate functions on the fly. Consider this example: kv = [foo: 1, bar: 2] Enum.each kv, fn {k, v} -> def unquote(k)(), do: unquote(v) end In the example above, we have generated the functions `foo/0` and `bar/0` dynamically. Now, imagine that, we want to convert this functionality into a macro: defmacro defkv(kv) do Enum.map kv, fn {k, v} -> quote do def unquote(k)(), do: unquote(v) end end end We can invoke this macro as: defkv [foo: 1, bar: 2] However, we can't invoke it as follows: kv = [foo: 1, bar: 2] defkv kv This is because the macro is expecting its arguments to be a keyword list at **compilation** time. Since in the example above we are passing the representation of the variable `kv`, our code fails. This is actually a common pitfall when developing macros. We are assuming a particular shape in the macro. We can work around it by unquoting the variable inside the quoted expression: defmacro defkv(kv) do quote do Enum.each unquote(kv), fn {k, v} -> def unquote(k)(), do: unquote(v) end end end If you try to run our new macro, you will notice it won't even compile, complaining that the variables `k` and `v` do not exist. This is because of the ambiguity: `unquote(k)` can either be an unquote fragment, as previously, or a regular unquote as in `unquote(kv)`. One solution to this problem is to disable unquoting in the macro, however, doing that would make it impossible to inject the `kv` representation into the tree. That's when the `:bind_quoted` option comes to the rescue (again!). By using `:bind_quoted`, we can automatically disable unquoting while still injecting the desired variables into the tree: defmacro defkv(kv) do quote bind_quoted: [kv: kv] do Enum.each kv, fn {k, v} -> def unquote(k)(), do: unquote(v) end end end In fact, the `:bind_quoted` option is recommended every time one desires to inject a value into the quote. """ defmacro quote(opts, block) @doc """ Unquotes the given expression from inside a macro. ## Examples Imagine the situation you have a variable `value` and you want to inject it inside some quote. The first attempt would be: value = 13 quote do: sum(1, value, 3) Which would then return: {:sum, [], [1, {:value, [], quoted}, 3]} Which is not the expected result. For this, we use unquote: value = 13 quote do: sum(1, unquote(value), 3) #=> {:sum, [], [1, 13, 3]} """ defmacro unquote(:unquote)(expr) @doc """ Unquotes the given list expanding its arguments. Similar to unquote. ## Examples values = [2, 3, 4] quote do: sum(1, unquote_splicing(values), 5) #=> {:sum, [], [1, 2, 3, 4, 5]} """ defmacro unquote(:unquote_splicing)(expr) @doc ~S""" Comprehensions allow you to quickly build a data structure from an enumerable or a bitstring. Let's start with an example: iex> for n <- [1, 2, 3, 4], do: n * 2 [2, 4, 6, 8] A comprehension accepts many generators and filters. Enumerable generators are defined using `<-`: # A list generator: iex> for n <- [1, 2, 3, 4], do: n * 2 [2, 4, 6, 8] # A comprehension with two generators iex> for x <- [1, 2], y <- [2, 3], do: x*y [2, 3, 4, 6] Filters can also be given: # A comprehension with a generator and a filter iex> for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n [2, 4, 6] Note generators can also be used to filter as it removes any value that doesn't match the left side of `<-`: iex> for {:user, name} <- [user: "john", admin: "john", user: "meg"] do ...> String.upcase(name) ...> end ["JOHN", "MEG"] Bitstring generators are also supported and are very useful when you need to organize bitstring streams: iex> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>> iex> for <>, do: {r, g, b} [{213, 45, 132}, {64, 76, 32}, {76, 0, 0}, {234, 32, 15}] Variable assignments inside the comprehension, be it in generators, filters or inside the block, are not reflected outside of the comprehension. ## Into In the examples above, the result returned by the comprehension was always a list. The returned result can be configured by passing an `:into` option, that accepts any structure as long as it implements the `Collectable` protocol. For example, we can use bitstring generators with the `:into` option to easily remove all spaces in a string: iex> for <>, c != ?\s, into: "", do: <> "helloworld" The `IO` module provides streams, that are both `Enumerable` and `Collectable`, here is an upcase echo server using comprehensions: for line <- IO.stream(:stdio, :line), into: IO.stream(:stdio, :line) do String.upcase(line) end """ defmacro for(args) @doc """ Defines an anonymous function. ## Examples iex> add = fn a, b -> a + b end iex> add.(1, 2) 3 """ defmacro unquote(:fn)(clauses) @doc """ Internal special form for block expressions. This is the special form used whenever we have a block of expressions in Elixir. This special form is private and should not be invoked directly: iex> quote do: (1; 2; 3) {:__block__, [], [1, 2, 3]} """ defmacro __block__(args) @doc """ Captures or creates an anonymous function. ## Capture The capture operator is most commonly used to capture a function with given name and arity from a module: iex> fun = &Kernel.is_atom/1 iex> fun.(:atom) true iex> fun.("string") false In the example above, we captured `Kernel.is_atom/1` as an anonymous function and then invoked it. The capture operator can also be used to capture local functions, including private ones, and imported functions by omitting the module name: &local_function/1 ## Anonymous functions The capture operator can also be used to partially apply functions, where `&1`, `&2` and so on can be used as value placeholders. For example: iex> double = &(&1 * 2) iex> double.(2) 4 In other words, `&(&1 * 2)` is equivalent to `fn x -> x * 2 end`. Another example using a local function: iex> fun = &is_atom(&1) iex> fun.(:atom) true The `&` operator can be used with more complex expressions: iex> fun = &(&1 + &2 + &3) iex> fun.(1, 2, 3) 6 As well as with lists and tuples: iex> fun = &{&1, &2} iex> fun.(1, 2) {1, 2} iex> fun = &[&1|&2] iex> fun.(1, 2) [1|2] The only restrictions when creating anonymous functions is that at least one placeholder must be present, i.e. it must contain at least `&1`: # No placeholder fails to compile &var # Block expressions are also not supported &(foo(&1, &2); &3 + &4) """ defmacro unquote(:&)(expr) @doc """ Internal special form to hold aliases information. It is usually compiled to an atom: iex> quote do: Foo.Bar {:__aliases__, [alias: false], [:Foo, :Bar]} Elixir represents `Foo.Bar` as `__aliases__` so calls can be unambiguously identified by the operator `:.`. For example: iex> quote do: Foo.bar {{:., [], [{:__aliases__, [alias: false], [:Foo]}, :bar]}, [], []} Whenever an expression iterator sees a `:.` as the tuple key, it can be sure that it represents a call and the second argument in the list is an atom. On the other hand, aliases holds some properties: 1. The head element of aliases can be any term that must expand to an atom at compilation time. 2. The tail elements of aliases are guaranteed to always be atoms. 3. When the head element of aliases is the atom `:Elixir`, no expansion happen. """ defmacro __aliases__(args) @doc """ Calls the overriden function when overriding it with `defoverridable`. See `Kernel.defoverridable` for more information and documentation. """ defmacro super(args) @doc """ Matches the given expression against the given clauses. ## Examples case thing do {:selector, i, value} when is_integer(i) -> value value -> value end In the example above, we match `thing` against each clause "head" and execute the clause "body" corresponding to the first clause that matches. If no clause matches, an error is raised. ## Variables handling Notice that variables bound in a clause "head" do not leak to the outer context: case data do {:ok, value} -> value :error -> nil end value #=> unbound variable value However, variables explicitly bound in the clause "body" are accessible from the outer context: value = 7 case lucky? do false -> value = 13 true -> true end value #=> 7 or 13 In the example above, value is going to be `7` or `13` depending on the value of `lucky?`. In case `value` has no previous value before case, clauses that do not explicitly bind a value have the variable bound to `nil`. """ defmacro case(condition, clauses) @doc """ Evaluates the expression corresponding to the first clause that evaluates to truth value. Raises an error if all conditions evaluate to `nil` or `false`. ## Examples cond do 1 + 1 == 1 -> "This will never match" 2 * 2 != 4 -> "Nor this" true -> "This will" end """ defmacro cond(clauses) @doc ~S""" Evaluates the given expressions and handle any error, exit or throw that may have happened. ## Examples try do do_something_that_may_fail(some_arg) rescue ArgumentError -> IO.puts "Invalid argument given" catch value -> IO.puts "caught #{value}" else value -> IO.puts "Success! The result was #{value}" after IO.puts "This is printed regardless if it failed or succeed" end The rescue clause is used to handle exceptions, while the catch clause can be used to catch thrown values. The else clause can be used to control flow based on the result of the expression. Catch, rescue and else clauses work based on pattern matching. Note that calls inside `try` are not tail recursive since the VM needs to keep the stacktrace in case an exception happens. ## Rescue clauses Besides relying on pattern matching, rescue clauses provides some conveniences around exceptions that allows one to rescue an exception by its name. All the following formats are valid rescue expressions: try do UndefinedModule.undefined_function rescue UndefinedFunctionError -> nil end try do UndefinedModule.undefined_function rescue [UndefinedFunctionError] -> nil end # rescue and bind to x try do UndefinedModule.undefined_function rescue x in [UndefinedFunctionError] -> nil end # rescue all and bind to x try do UndefinedModule.undefined_function rescue x -> nil end ## Erlang errors Erlang errors are transformed into Elixir ones during rescue: try do :erlang.error(:badarg) rescue ArgumentError -> :ok end The most common Erlang errors will be transformed into their Elixir counter-part. Those which are not will be transformed into `ErlangError`: try do :erlang.error(:unknown) rescue ErlangError -> :ok end In fact, ErlangError can be used to rescue any error that is not an Elixir error proper. For example, it can be used to rescue the earlier `:badarg` error too, prior to transformation: try do :erlang.error(:badarg) rescue ErlangError -> :ok end ## Catching throws and exits The catch clause can be used to catch throws values and exits. try do exit(:shutdown) catch :exit, :shutdown -> IO.puts "Exited with shutdown reason" end try do throw(:sample) catch :throw, :sample -> IO.puts "sample thrown" end catch values also support `:error`, as in Erlang, although it is commonly avoided in favor of raise/rescue control mechanisms. ## Else clauses Else clauses allow the result of the expression to be pattern matched on: x = 2 try do 1 / x rescue ArithmeticError -> :infinity else y when y < 1 and y > -1 -> :small _ -> :large end If an else clause is not present the result of the expression will be return, if no exceptions are raised: x = 1 ^x = try do 1 / x rescue ArithmeticError -> :infinity end However when an else clause is present but the result of the expression does not match any of the patterns an exception will be raised. This exception will not be caught by a catch or rescue in the same try: x = 1 try do try do 1 / x rescue # The TryClauseError can not be rescued here: TryClauseError -> :error_a else 0 -> :small end rescue # The TryClauseError is rescued here: TryClauseError -> :error_b end Similarly an exception inside an else clause is not caught or rescued inside the same try: try do try do nil catch # The exit(1) call below can not be caught here: :exit, _ -> :exit_a else _ -> exit(1) end catch # The exit is caught here: :exit, _ -> :exit_b end This means the VM no longer needs to keep the stacktrace once inside an else clause and so tail recursion is possible when using a `try` with a tail call as the final call inside an else clause. The same is `true` for `rescue` and `catch` clauses. ## Variable handling Since an expression inside `try` may not have been evaluated due to an exception, any variable created inside `try` cannot be accessed externally. For instance: try do x = 1 do_something_that_may_fail(same_arg) :ok catch _, _ -> :failed end x #=> unbound variable `x` In the example above, `x` cannot be accessed since it was defined inside the `try` clause. A common practice to address this issue is to return the variables defined inside `try`: x = try do x = 1 do_something_that_may_fail(same_arg) x catch _, _ -> :failed end """ defmacro try(args) @doc """ Checks if there is a message matching the given clauses in the current process mailbox. In case there is no such message, the current process hangs until a message arrives or waits until a given timeout value. ## Examples receive do {:selector, i, value} when is_integer(i) -> value value when is_atom(value) -> value _ -> IO.puts :stderr, "Unexpected message received" end An optional after clause can be given in case the message was not received after the specified period of time: receive do {:selector, i, value} when is_integer(i) -> value value when is_atom(value) -> value _ -> IO.puts :stderr, "Unexpected message received" after 5000 -> IO.puts :stderr, "No message in 5 seconds" end The `after` clause can be specified even if there are no match clauses. There are two special cases for the timeout value given to `after` * `:infinity` - the process should wait indefinitely for a matching message, this is the same as not using a timeout * 0 - if there is no matching message in the mailbox, the timeout will occur immediately ## Variables handling The `receive` special form handles variables exactly as the `case` special macro. For more information, check the docs for `case/2`. """ defmacro receive(args) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/kernel/typespec.ex000066400000000000000000001015251254730255300234030ustar00rootroot00000000000000defmodule Kernel.Typespec do @moduledoc ~S""" Provides macros and functions for working with typespecs. Elixir comes with a notation for declaring types and specifications. Elixir is dynamically typed, as such typespecs are never used by the compiler to optimize or modify code. Still, using typespecs is useful as documentation and tools such as [Dialyzer](http://www.erlang.org/doc/man/dialyzer.html) can analyze the code with typespecs to find bugs. The attributes `@type`, `@opaque`, `@typep`, `@spec` and `@callback` available in modules are handled by the equivalent macros defined by this module. See sub-sections "Defining a type" and "Defining a specification" below. ## Types and their syntax The type syntax provided by Elixir is fairly similar to the one in [Erlang](http://www.erlang.org/doc/reference_manual/typespec.html). Most of the built-in types provided in Erlang (for example, `pid()`) are expressed the same way: `pid()` or simply `pid`. Parameterized types are also supported (`list(integer)`) and so are remote types (`Enum.t`). Integers and atom literals are allowed as types (ex. `1`, `:atom` or `false`). All other types are built of unions of predefined types. Certain shorthands are allowed, such as `[...]`, `<<>>` and `{...}`. ### Predefined types Type :: any # the top type, the set of all terms | none # the bottom type, contains no terms | pid | port | reference | Atom | Bitstring | float | Fun | Integer | List | Map | Tuple | Union | UserDefined # Described in section "Defining a type" Atom :: atom | ElixirAtom # `:foo`, `:bar`, ... Bitstring :: <<>> | << _ :: M >> # M is a positive integer | << _ :: _ * N >> # N is a positive integer | << _ :: M, _ :: _ * N >> Fun :: (... -> any) # any function | (... -> Type) # any arity, returning Type | (() -> Type)) | (TList -> Type) Integer :: integer | ElixirInteger # ..., -1, 0, 1, ... 42 ... | ElixirInteger..ElixirInteger # an integer range List :: list(Type) # proper list ([]-terminated) | improper_list(Type1, Type2) # Type1=contents, Type2=termination | maybe_improper_list(Type1, Type2) # Type1 and Type2 as above | nonempty_list(Type) # proper non-empty list | [] # empty list | [Type] # shorthand for list(Type) | [...] # shorthand for nonempty_list() | [Type, ...] # shorthand for nonempty_list(Type) | [Keyword] Map :: map() # map of any size | %{} # map of any size | %Struct{} # struct (see defstruct/1) | %Struct{Keyword} | %{Keyword} | %{Pairs} Tuple :: tuple # a tuple of any size | {} # empty tuple | {TList} | record(Atom) # record (see Record) | record(Atom, Keyword) Keyword :: ElixirAtom: Type | ElixirAtom: Type, Keyword Pairs :: Type => Type | Type => Type, Pairs TList :: Type | Type, TList Union :: Type | Type ### Bit strings Bit string with a base size of 3: << _ :: 3 >> Bit string with a unit size of 8: << _ :: _ * 8 >> ### Anonymous functions Any anonymous function: ((...) -> any) (... -> any) Anonymous function with arity of zero: (() -> type) Anonymous function with some arity: ((type, type) -> type) (type, type -> type) ## Built-in types Built-in type | Defined as :-------------------- | :--------- `term` | `any` `binary` | `<< _ :: _ * 8 >>` `bitstring` | `<< _ :: _ * 1 >>` `boolean` | `false` \| `true` `byte` | `0..255` `char` | `0..0x10ffff` `number` | `integer` \| `float` `char_list` | `[char]` `list` | `[any]` `maybe_improper_list` | `maybe_improper_list(any, any)` `nonempty_list` | `nonempty_list(any)` `iodata` | `iolist` \| `binary` `iolist` | `maybe_improper_list(byte` \| `binary` \| `iolist, binary` \| `[])` `module` | `atom` \| `tuple` `mfa` | `{atom, atom, arity}` `arity` | `0..255` `node` | `atom` `timeout` | `:infinity` \| `non_neg_integer` `no_return` | `none` `fun` | `(... -> any)` Some built-in types cannot be expressed with valid syntax according to the language defined above. Built-in type | Can be interpreted as :---------------- | :-------------------- `non_neg_integer` | `0..` `pos_integer` | `1..` `neg_integer` | `..-1` Types defined in other modules are referred to as "remote types", they are referenced as `Module.type_name` (ex. `Enum.t` or `String.t`). ## Defining a type @type type_name :: type @typep type_name :: type @opaque type_name :: type A type defined with `@typep` is private. An opaque type, defined with `@opaque` is a type where the internal structure of the type will not be visible, but the type is still public. Types can be parameterized by defining variables as parameters, these variables can then be used to define the type. @type dict(key, value) :: [{key, value}] ## Defining a specification @spec function_name(type1, type2) :: return_type @callback function_name(type1, type2) :: return_type Callbacks are used to define the callbacks functions of behaviours (see `Behaviour`). Guards can be used to restrict type variables given as arguments to the function. @spec function(arg) :: [arg] when arg: atom Type variables with no restriction can also be defined. @spec function(arg) :: [arg] when arg: var Specifications can be overloaded just like ordinary functions. @spec function(integer) :: atom @spec function(atom) :: integer ## Notes Elixir discourages the use of type `string` as it might be confused with binaries which are referred to as "strings" in Elixir (as opposed to character lists). In order to use the type that is called `string` in Erlang, one has to use the `char_list` type which is a synonym for `string`. If you use `string`, you'll get a warning from the compiler. If you want to refer to the "string" type (the one operated on by functions in the `String` module), use `String.t` type instead. """ @doc """ Defines a type. This macro is responsible for handling the attribute `@type`. ## Examples @type my_type :: atom """ defmacro deftype(type) do quote do Kernel.Typespec.deftype(:type, unquote(Macro.escape(type, unquote: true)), __ENV__) end end @doc """ Defines an opaque type. This macro is responsible for handling the attribute `@opaque`. ## Examples @opaque my_type :: atom """ defmacro defopaque(type) do quote do Kernel.Typespec.deftype(:opaque, unquote(Macro.escape(type, unquote: true)), __ENV__) end end @doc """ Defines a private type. This macro is responsible for handling the attribute `@typep`. ## Examples @typep my_type :: atom """ defmacro deftypep(type) do quote do Kernel.Typespec.deftype(:typep, unquote(Macro.escape(type, unquote: true)), __ENV__) end end @doc """ Defines a spec. This macro is responsible for handling the attribute `@spec`. ## Examples @spec add(number, number) :: number """ defmacro defspec(spec) do quote do Kernel.Typespec.defspec(:spec, unquote(Macro.escape(spec, unquote: true)), __ENV__) end end @doc """ Defines a callback. This macro is responsible for handling the attribute `@callback`. ## Examples @callback add(number, number) :: number """ defmacro defcallback(spec) do quote do Kernel.Typespec.defspec(:callback, unquote(Macro.escape(spec, unquote: true)), __ENV__) end end @doc """ Defines a `type`, `typep` or `opaque` by receiving a typespec expression. """ def define_type(kind, expr, doc \\ nil, env) do Module.store_typespec(env.module, kind, {kind, expr, doc, env}) end @doc """ Defines a `spec` by receiving a typespec expression. """ def define_spec(kind, expr, env) do Module.store_typespec(env.module, kind, {kind, expr, env}) end @doc """ Returns `true` if the current module defines a given type (private, opaque or not). This function is only available for modules being compiled. """ def defines_type?(module, name, arity) do finder = fn {_kind, expr, _doc, _caller} -> type_to_signature(expr) == {name, arity} end :lists.any(finder, Module.get_attribute(module, :type)) or :lists.any(finder, Module.get_attribute(module, :opaque)) end @doc """ Returns `true` if the current module defines a given spec. This function is only available for modules being compiled. """ def defines_spec?(module, name, arity) do finder = fn {_kind, expr, _caller} -> spec_to_signature(expr) == {name, arity} end :lists.any(finder, Module.get_attribute(module, :spec)) end @doc """ Returns `true` if the current module defines a callback. This function is only available for modules being compiled. """ def defines_callback?(module, name, arity) do finder = fn {_kind, expr, _caller} -> spec_to_signature(expr) == {name, arity} end :lists.any(finder, Module.get_attribute(module, :callback)) end @doc """ Converts a spec clause back to Elixir AST. """ def spec_to_ast(name, spec) def spec_to_ast(name, {:type, line, :fun, [{:type, _, :product, args}, result]}) do meta = [line: line] body = {name, meta, Enum.map(args, &typespec_to_ast/1)} vars = args ++ [result] |> Enum.flat_map(&collect_vars/1) |> Enum.uniq |> Enum.map(&{&1, {:var, meta, nil}}) spec = {:::, meta, [body, typespec_to_ast(result)]} if vars == [] do spec else {:when, meta, [spec, vars]} end end def spec_to_ast(name, {:type, line, :fun, []}) do {:::, [line: line], [{name, [line: line], []}, quote(do: term)]} end def spec_to_ast(name, {:type, line, :bounded_fun, [{:type, _, :fun, [{:type, _, :product, args}, result]}, constraints]}) do guards = for {:type, _, :constraint, [{:atom, _, :is_subtype}, [{:var, _, var}, type]]} <- constraints do {var, typespec_to_ast(type)} end meta = [line: line] vars = args ++ [result] |> Enum.flat_map(&collect_vars/1) |> Enum.uniq |> Kernel.--(Keyword.keys(guards)) |> Enum.map(&{&1, {:var, meta, nil}}) args = for arg <- args, do: typespec_to_ast(arg) {:when, meta, [ {:::, meta, [{name, [line: line], args}, typespec_to_ast(result)]}, guards ++ vars ]} end @doc """ Converts a type clause back to Elixir AST. """ def type_to_ast(type) def type_to_ast({{:record, record}, fields, args}) when is_atom(record) do fields = for field <- fields, do: typespec_to_ast(field) args = for arg <- args, do: typespec_to_ast(arg) type = {:{}, [], [record|fields]} quote do: unquote(record)(unquote_splicing(args)) :: unquote(type) end def type_to_ast({name, type, args}) do args = for arg <- args, do: typespec_to_ast(arg) quote do: unquote(name)(unquote_splicing(args)) :: unquote(typespec_to_ast(type)) end @doc """ Returns all type docs available from the module's beam code. The result is returned as a list of tuples where the first element is the pair of type name and arity and the second element is the documentation. The module must have a corresponding beam file which can be located by the runtime system. """ @spec beam_typedocs(module | binary) :: [tuple] | nil def beam_typedocs(module) when is_atom(module) or is_binary(module) do case abstract_code(module) do {:ok, abstract_code} -> type_docs = for {:attribute, _, :typedoc, tup} <- abstract_code, do: tup :lists.flatten(type_docs) _ -> nil end end @doc """ Returns all types available from the module's beam code. The result is returned as a list of tuples where the first element is the type (`:typep`, `:type` and `:opaque`). The module must have a corresponding beam file which can be located by the runtime system. """ @spec beam_types(module | binary) :: [tuple] | nil def beam_types(module) when is_atom(module) or is_binary(module) do case abstract_code(module) do {:ok, abstract_code} -> exported_types = for {:attribute, _, :export_type, types} <- abstract_code, do: types exported_types = :lists.flatten(exported_types) for {:attribute, _, kind, {name, _, args} = type} <- abstract_code, kind in [:opaque, :type] do cond do kind == :opaque -> {:opaque, type} {name, length(args)} in exported_types -> {:type, type} true -> {:typep, type} end end _ -> nil end end @doc """ Returns all specs available from the module's beam code. The result is returned as a list of tuples where the first element is spec name and arity and the second is the spec. The module must have a corresponding beam file which can be located by the runtime system. """ @spec beam_specs(module | binary) :: [tuple] | nil def beam_specs(module) when is_atom(module) or is_binary(module) do from_abstract_code(module, :spec) end @doc """ Returns all callbacks available from the module's beam code. The result is returned as a list of tuples where the first element is spec name and arity and the second is the spec. The module must have a corresponding beam file which can be located by the runtime system. """ @spec beam_callbacks(module | binary) :: [tuple] | nil def beam_callbacks(module) when is_atom(module) or is_binary(module) do from_abstract_code(module, :callback) end defp from_abstract_code(module, kind) do case abstract_code(module) do {:ok, abstract_code} -> for {:attribute, _, abs_kind, value} <- abstract_code, kind == abs_kind, do: value :error -> nil end end defp abstract_code(module) do case :beam_lib.chunks(abstract_code_beam(module), [:abstract_code]) do {:ok, {_, [{:abstract_code, {_raw_abstract_v1, abstract_code}}]}} -> {:ok, abstract_code} _ -> :error end end defp abstract_code_beam(module) when is_atom(module) do case :code.get_object_code(module) do {^module, beam, _filename} -> beam :error -> module end end defp abstract_code_beam(binary) when is_binary(binary) do binary end ## Helpers @doc false def spec_to_signature({:when, _, [spec, _]}), do: type_to_signature(spec) def spec_to_signature(other), do: type_to_signature(other) @doc false def type_to_signature({:::, _, [{name, _, context}, _]}) when is_atom(name) and is_atom(context), do: {name, 0} def type_to_signature({:::, _, [{name, _, args}, _]}) when is_atom(name), do: {name, length(args)} ## Macro callbacks @doc false def defspec(kind, expr, caller) do Module.store_typespec(caller.module, kind, {kind, expr, caller}) end @doc false def deftype(kind, expr, caller) do module = caller.module doc = Module.get_attribute(module, :typedoc) Module.delete_attribute(module, :typedoc) Module.store_typespec(module, kind, {kind, expr, doc, caller}) end ## Translation from Elixir AST to typespec AST @doc false def translate_type(kind, {:::, _, [{name, _, args}, definition]}, doc, caller) when is_atom(name) and name != ::: do args = if is_atom(args) do [] else for(arg <- args, do: variable(arg)) end vars = for {:var, _, var} <- args, do: var spec = typespec(definition, vars, caller) vars = for {:var, _, _} = var <- args, do: var type = {name, spec, vars} arity = length(vars) {kind, export} = case kind do :type -> {:type, true} :typep -> {:type, false} :opaque -> {:opaque, true} end if not export and doc do :elixir_errors.warn(caller.line, caller.file, "type #{name}/#{arity} is private, " <> "@typedoc's are always discarded for private types") end {{kind, {name, arity}, type}, caller.line, export, doc} end def translate_type(_kind, other, _doc, caller) do type_spec = Macro.to_string(other) compile_error caller, "invalid type specification: #{type_spec}" end @doc false def translate_spec(kind, {:when, _meta, [spec, guard]}, caller) do translate_spec(kind, spec, guard, caller) end def translate_spec(kind, spec, caller) do translate_spec(kind, spec, [], caller) end defp translate_spec(kind, {:::, meta, [{name, _, args}, return]}, guard, caller) when is_atom(name) and name != ::: do if is_atom(args), do: args = [] unless Keyword.keyword?(guard) do guard = Macro.to_string(guard) compile_error caller, "expected keywords as guard in function type specification, got: #{guard}" end vars = Keyword.keys(guard) constraints = guard_to_constraints(guard, vars, meta, caller) spec = {:type, line(meta), :fun, fn_args(meta, args, return, vars, caller)} if constraints != [] do spec = {:type, line(meta), :bounded_fun, [spec, constraints]} end arity = length(args) {{kind, {name, arity}, spec}, caller.line} end defp translate_spec(_kind, spec, _guard, caller) do spec = Macro.to_string(spec) compile_error caller, "invalid function type specification: #{spec}" end defp guard_to_constraints(guard, vars, meta, caller) do line = line(meta) :lists.foldl(fn {_name, {:var, _, context}}, acc when is_atom(context) -> acc {name, type}, acc -> constraint = [{:atom, line, :is_subtype}, [{:var, line, name}, typespec(type, vars, caller)]] type = {:type, line, :constraint, constraint} [type|acc] end, [], guard) |> :lists.reverse end ## To AST conversion defp collect_vars({:ann_type, _line, args}) when is_list(args) do [] end defp collect_vars({:type, _line, _kind, args}) when is_list(args) do Enum.flat_map(args, &collect_vars/1) end defp collect_vars({:remote_type, _line, args}) when is_list(args) do Enum.flat_map(args, &collect_vars/1) end defp collect_vars({:typed_record_field, _line, type}) do collect_vars(type) end defp collect_vars({:paren_type, _line, [type]}) do collect_vars(type) end defp collect_vars({:var, _line, var}) do [erl_to_ex_var(var)] end defp collect_vars(_) do [] end defp typespec_to_ast({:user_type, line, name, args}) do typespec_to_ast({:type, line, name, args}) end defp typespec_to_ast({:type, line, :tuple, :any}) do {:tuple, [line: line], []} end defp typespec_to_ast({:type, line, :tuple, args}) do args = for arg <- args, do: typespec_to_ast(arg) {:{}, [line: line], args} end defp typespec_to_ast({:type, _line, :list, [{:type, _, :union, unions} = arg]}) do case unpack_typespec_kw(unions, []) do {:ok, ast} -> ast :error -> [typespec_to_ast(arg)] end end defp typespec_to_ast({:type, line, :list, []}) do {:list, [line: line], []} end defp typespec_to_ast({:type, _line, :list, [arg]}) do [typespec_to_ast(arg)] end defp typespec_to_ast({:type, line, :nonempty_list, []}) do [{:..., [line: line], nil}] end defp typespec_to_ast({:type, line, :nonempty_list, [arg]}) do [typespec_to_ast(arg), {:..., [line: line], nil}] end defp typespec_to_ast({:type, line, :map, :any}) do {:map, [line: line], []} end defp typespec_to_ast({:type, line, :map, fields}) do fields = Enum.map fields, fn # OTP 18 {:type, _, :map_field_assoc, [k, v]} -> {typespec_to_ast(k), typespec_to_ast(v)} # OTP 17 {:type, _, :map_field_assoc, k, v} -> {typespec_to_ast(k), typespec_to_ast(v)} end {struct, fields} = Keyword.pop(fields, :__struct__) map = {:%{}, [line: line], fields} if struct do {:%, [line: line], [struct, map]} else map end end defp typespec_to_ast({:type, line, :binary, [arg1, arg2]}) do [arg1, arg2] = for arg <- [arg1, arg2], do: typespec_to_ast(arg) cond do arg2 == 0 -> quote line: line, do: <<_ :: unquote(arg1)>> arg1 == 0 -> quote line: line, do: <<_ :: _ * unquote(arg2)>> true -> quote line: line, do: <<_ :: unquote(arg1) * unquote(arg2)>> end end defp typespec_to_ast({:type, line, :union, args}) do args = for arg <- args, do: typespec_to_ast(arg) Enum.reduce Enum.reverse(args), fn(arg, expr) -> {:|, [line: line], [arg, expr]} end end defp typespec_to_ast({:type, line, :fun, [{:type, _, :product, args}, result]}) do args = for arg <- args, do: typespec_to_ast(arg) [{:->, [line: line], [args, typespec_to_ast(result)]}] end defp typespec_to_ast({:type, line, :fun, [args, result]}) do [{:->, [line: line], [[typespec_to_ast(args)], typespec_to_ast(result)]}] end defp typespec_to_ast({:type, line, :fun, []}) do typespec_to_ast({:type, line, :fun, [{:type, line, :any}, {:type, line, :any, []} ]}) end defp typespec_to_ast({:type, line, :range, [left, right]}) do {:.., [line: line], [typespec_to_ast(left), typespec_to_ast(right)]} end defp typespec_to_ast({:type, _line, nil, []}) do [] end defp typespec_to_ast({:type, line, name, args}) do args = for arg <- args, do: typespec_to_ast(arg) {name, [line: line], args} end defp typespec_to_ast({:var, line, var}) do {erl_to_ex_var(var), line, nil} end defp typespec_to_ast({:op, line, op, arg}) do {op, [line: line], [typespec_to_ast(arg)]} end # Special shortcut(s) defp typespec_to_ast({:remote_type, line, [{:atom, _, :elixir}, {:atom, _, :char_list}, []]}) do typespec_to_ast({:type, line, :char_list, []}) end defp typespec_to_ast({:remote_type, line, [{:atom, _, :elixir}, {:atom, _, :as_boolean}, [arg]]}) do typespec_to_ast({:type, line, :as_boolean, [arg]}) end defp typespec_to_ast({:remote_type, line, [mod, name, args]}) do args = for arg <- args, do: typespec_to_ast(arg) dot = {:., [line: line], [typespec_to_ast(mod), typespec_to_ast(name)]} {dot, [line: line], args} end defp typespec_to_ast({:ann_type, line, [var, type]}) do {:::, [line: line], [typespec_to_ast(var), typespec_to_ast(type)]} end defp typespec_to_ast({:typed_record_field, {:record_field, line, {:atom, line1, name}}, type}) do typespec_to_ast({:ann_type, line, [{:var, line1, name}, type]}) end defp typespec_to_ast({:type, _, :any}) do quote do: ... end defp typespec_to_ast({:paren_type, _, [type]}) do typespec_to_ast(type) end defp typespec_to_ast({t, _line, atom}) when is_atom(t) do atom end defp typespec_to_ast(other), do: other defp erl_to_ex_var(var) do case Atom.to_string(var) do <<"_", c :: binary-size(1), rest :: binary>> -> String.to_atom("_#{String.downcase(c)}#{rest}") <> -> String.to_atom("#{String.downcase(c)}#{rest}") end end ## To typespec conversion defp line(meta) do case :lists.keyfind(:line, 1, meta) do {:line, line} -> line false -> 0 end end # Handle unions defp typespec({:|, meta, [_, _]} = exprs, vars, caller) do exprs = collect_union(exprs) union = for e <- exprs, do: typespec(e, vars, caller) {:type, line(meta), :union, union} end # Handle binaries defp typespec({:<<>>, meta, []}, _, _) do {:type, line(meta), :binary, [{:integer, line(meta), 0}, {:integer, line(meta), 0}]} end defp typespec({:<<>>, meta, [{:::, _, [{:_, meta1, atom}, {:*, _, [{:_, meta2, atom}, unit]}]}]}, _, _) when is_atom(atom) do {:type, line(meta), :binary, [{:integer, line(meta1), 0}, {:integer, line(meta2), unit}]} end defp typespec({:<<>>, meta, [{:::, meta1, [{:_, meta2, atom}, base]}]}, _, _) when is_atom(atom) do {:type, line(meta), :binary, [{:integer, line(meta1), base}, {:integer, line(meta2), 0}]} end ## Handle maps and structs defp typespec({:map, meta, args}, _vars, _caller) when args == [] or is_atom(args) do {:type, line(meta), :map, :any} end defp typespec({:%{}, meta, fields}, vars, caller) do fields = # TODO: Remove else once we support only OTP >18 if :erlang.system_info(:otp_release) >= '18' do :lists.map(fn {k, v} -> {:type, line(meta), :map_field_assoc, [typespec(k, vars, caller), typespec(v, vars, caller)]} end, fields) else :lists.map(fn {k, v} -> {:type, line(meta), :map_field_assoc, typespec(k, vars, caller), typespec(v, vars, caller)} end, fields) end {:type, line(meta), :map, fields} end defp typespec({:%, _, [name, {:%{}, meta, fields}]}, vars, caller) do module = Macro.expand(name, caller) struct = if module == caller.module do Module.get_attribute(module, :struct) || compile_error(caller, "struct is not defined for #{Macro.to_string(name)}") else module.__struct__ end struct = :lists.map(fn {field, _} -> {field, quote do: term()} end, Map.to_list(struct)) :lists.foreach(fn {field, _} -> unless Keyword.has_key?(struct, field) do compile_error(caller, "undefined field #{field} on struct #{Macro.to_string(name)}") end end, fields) fields = Keyword.merge(struct, [__struct__: module] ++ fields) typespec({:%{}, meta, fields}, vars, caller) end # Handle records defp typespec({:record, meta, [atom]}, vars, caller) do typespec({:record, meta, [atom, []]}, vars, caller) end defp typespec({:record, meta, [atom, fields]}, vars, caller) do case Macro.expand({atom, [], [{atom, [], []}]}, caller) do keyword when is_list(keyword) -> keyword = :lists.map(fn {field, _} -> {field, quote do: term()} end, keyword) :lists.foreach(fn {field, _} -> unless Keyword.has_key?(keyword, field) do compile_error(caller, "undefined field #{field} on record #{inspect atom}") end end, fields) fields = Keyword.merge(keyword, fields) types = Keyword.values(fields) typespec({:{}, meta, [atom|types]}, vars, caller) _ -> compile_error(caller, "unknown record #{inspect atom}") end end # Handle ranges defp typespec({:.., meta, args}, vars, caller) do args = for arg <- args, do: typespec(arg, vars, caller) {:type, line(meta), :range, args} end # Handle special forms defp typespec({:__MODULE__, _, atom}, vars, caller) when is_atom(atom) do typespec(caller.module, vars, caller) end defp typespec({:__aliases__, _, _} = alias, vars, caller) do atom = Macro.expand alias, caller typespec(atom, vars, caller) end # Handle funs defp typespec([{:->, meta, [arguments, return]}], vars, caller) when is_list(arguments) do args = fn_args(meta, arguments, return, vars, caller) {:type, line(meta), :fun, args} end # Handle type operator defp typespec({:::, meta, [var, expr]}, vars, caller) do left = typespec(var, [elem(var, 0)|vars], caller) right = typespec(expr, vars, caller) {:ann_type, line(meta), [left, right]} end # Handle unary ops defp typespec({op, meta, [integer]}, _, _) when op in [:+, :-] and is_integer(integer) do {:op, line(meta), op, {:integer, line(meta), integer}} end # Handle remote calls defp typespec({{:., meta, [remote, name]}, _, args} = orig, vars, caller) do remote = Macro.expand remote, caller unless is_atom(remote) do compile_error(caller, "invalid remote in typespec: #{Macro.to_string(orig)}") end remote_type({typespec(remote, vars, caller), meta, typespec(name, vars, caller), args}, vars, caller) end # Handle tuples defp typespec({:tuple, meta, args}, _vars, _caller) when args == [] or is_atom(args) do {:type, line(meta), :tuple, :any} end defp typespec({:{}, meta, t}, vars, caller) when is_list(t) do args = for e <- t, do: typespec(e, vars, caller) {:type, line(meta), :tuple, args} end defp typespec({left, right}, vars, caller) do typespec({:{}, [], [left, right]}, vars, caller) end # Handle blocks defp typespec({:__block__, _meta, [arg]}, vars, caller) do typespec(arg, vars, caller) end # Handle variables or local calls defp typespec({name, meta, atom}, vars, caller) when is_atom(atom) do if :lists.member(name, vars) do {:var, line(meta), name} else typespec({name, meta, []}, vars, caller) end end # Handle local calls defp typespec({type, meta, arguments}, vars, caller) when type in [:string, :nonempty_string] do :elixir_errors.warn caller.line, caller.file, "#{type}() type use is discouraged. For character lists, use " <> "char_list() type, for strings, String.t()\n#{Exception.format_stacktrace(Macro.Env.stacktrace(caller))}" arguments = for arg <- arguments, do: typespec(arg, vars, caller) {:type, line(meta), type, arguments} end defp typespec({:char_list, _meta, []}, vars, caller) do typespec((quote do: :elixir.char_list()), vars, caller) end defp typespec({:as_boolean, _meta, [arg]}, vars, caller) do typespec((quote do: :elixir.as_boolean(unquote(arg))), vars, caller) end defp typespec({:fun, meta, args}, vars, caller) do args = for arg <- args, do: typespec(arg, vars, caller) {:type, line(meta), :fun, args} end defp typespec({name, meta, arguments}, vars, caller) do arguments = for arg <- arguments, do: typespec(arg, vars, caller) if :erlang.system_info(:otp_release) >= '18' do arity = length(arguments) type = if :erl_internal.is_type(name, arity), do: :type, else: :user_type {type, line(meta), name, arguments} else {:type, line(meta), name, arguments} end end # Handle literals defp typespec(atom, _, _) when is_atom(atom) do {:atom, 0, atom} end defp typespec(integer, _, _) when is_integer(integer) do {:integer, 0, integer} end defp typespec([], vars, caller) do typespec({nil, [], []}, vars, caller) end defp typespec([{:..., _, atom}], vars, caller) when is_atom(atom) do typespec({:nonempty_list, [], []}, vars, caller) end defp typespec([spec, {:..., _, atom}], vars, caller) when is_atom(atom) do typespec({:nonempty_list, [], [spec]}, vars, caller) end defp typespec([spec], vars, caller) do typespec({:list, [], [spec]}, vars, caller) end defp typespec(list, vars, caller) when is_list(list) do [h|t] = :lists.reverse(list) union = :lists.foldl(fn(x, acc) -> {:|, [], [validate_kw(x, list, caller), acc]} end, validate_kw(h, list, caller), t) typespec({:list, [], [union]}, vars, caller) end defp typespec(other, _vars, caller) do compile_error(caller, "unexpected expression in typespec: #{Macro.to_string other}") end ## Helpers defp compile_error(caller, desc) do raise CompileError, file: caller.file, line: caller.line, description: desc end defp remote_type({remote, meta, name, arguments}, vars, caller) do arguments = for arg <- arguments, do: typespec(arg, vars, caller) {:remote_type, line(meta), [ remote, name, arguments ]} end defp collect_union({:|, _, [a, b]}), do: [a|collect_union(b)] defp collect_union(v), do: [v] defp validate_kw({key, _} = t, _, _caller) when is_atom(key), do: t defp validate_kw(_, original, caller) do compile_error(caller, "unexpected list in typespec: #{Macro.to_string original}") end defp fn_args(meta, args, return, vars, caller) do case [fn_args(meta, args, vars, caller), typespec(return, vars, caller)] do [{:type, _, :any}, {:type, _, :any, []}] -> [] x -> x end end defp fn_args(meta, [{:..., _, _}], _vars, _caller) do {:type, line(meta), :any} end defp fn_args(meta, args, vars, caller) do args = for arg <- args, do: typespec(arg, vars, caller) {:type, line(meta), :product, args} end defp variable({name, meta, _}) do {:var, line(meta), name} end defp unpack_typespec_kw([{:type, _, :tuple, [{:atom, _, atom}, type]}|t], acc) do unpack_typespec_kw(t, [{atom, typespec_to_ast(type)}|acc]) end defp unpack_typespec_kw([], acc) do {:ok, :lists.reverse(acc)} end defp unpack_typespec_kw(_, _acc) do :error end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/keyword.ex000066400000000000000000000444571254730255300217650ustar00rootroot00000000000000defmodule Keyword do @moduledoc """ A keyword is a list of tuples where the first element of the tuple is an atom and the second element can be any value. A keyword may have duplicated keys so it is not strictly a dictionary. However most of the functions in this module behave exactly as a dictionary and mimic the API defined by the `Dict` behaviour. For example, `Keyword.get/3` will get the first entry matching the given key, regardless if duplicated entries exist. Similarly, `Keyword.put/3` and `Keyword.delete/3` ensure all duplicated entries for a given key are removed when invoked. A handful of functions exist to handle duplicated keys, in particular, `Enum.into/2` allows creating new keywords without removing duplicated keys, `get_values/2` returns all values for a given key and `delete_first/2` deletes just one of the existing entries. The functions in Keyword do not guarantee any property when it comes to ordering. However, since a keyword list is simply a list, all the operations defined in `Enum` and `List` can be applied too, specially when ordering is required. """ @compile :inline_list_funcs @behaviour Dict @type key :: atom @type value :: any @type t :: [{key, value}] @type t(value) :: [{key, value}] @doc """ Returns `true` if `term` is a keyword list; otherwise returns `false`. """ @spec keyword?(term) :: boolean def keyword?(term) def keyword?([{key, _value} | rest]) when is_atom(key), do: keyword?(rest) def keyword?([]), do: true def keyword?(_other), do: false @doc """ Returns an empty keyword list, i.e. an empty list. """ @spec new :: t def new, do: [] @doc """ Creates a keyword from an enumerable. Duplicated entries are removed, the latest one prevails. Unlike `Enum.into(enumerable, [])`, `Keyword.new(enumerable)` guarantees the keys are unique. ## Examples iex> Keyword.new([{:b, 1}, {:a, 2}]) [a: 2, b: 1] """ @spec new(Enum.t) :: t def new(pairs) do new(pairs, fn pair -> pair end) end @doc """ Creates a keyword from an enumerable via the transformation function. Duplicated entries are removed, the latest one prevails. Unlike `Enum.into(enumerable, [], fun)`, `Keyword.new(enumerable, fun)` guarantees the keys are unique. ## Examples iex> Keyword.new([:a, :b], fn (x) -> {x, x} end) [b: :b, a: :a] """ @spec new(Enum.t, (term -> {key, value})) :: t def new(pairs, transform) when is_function(transform, 1) do fun = fn el, acc -> {k, v} = transform.(el) put_new(acc, k, v) end :lists.foldr(fun, [], Enum.reverse(pairs)) end @doc """ Gets the value for a specific `key`. If `key` does not exist, return the default value (`nil` if no default value). If duplicated entries exist, the first one is returned. Use `get_values/2` to retrieve all entries. ## Examples iex> Keyword.get([a: 1], :a) 1 iex> Keyword.get([a: 1], :b) nil iex> Keyword.get([a: 1], :b, 3) 3 """ @spec get(t, key) :: value @spec get(t, key, value) :: value def get(keywords, key, default \\ nil) when is_list(keywords) and is_atom(key) do case :lists.keyfind(key, 1, keywords) do {^key, value} -> value false -> default end end @doc """ Gets the value for a specific `key`. If `key` does not exist, lazily evaluates `fun` and returns its result. This is useful if the default value is very expensive to calculate or generally difficult to set-up and tear-down again. If duplicated entries exist, the first one is returned. Use `get_values/2` to retrieve all entries. ## Examples iex> keyword = [a: 1] iex> fun = fn -> ...> # some expensive operation here ...> :result ...> end iex> Keyword.get_lazy(keyword, :a, fun) 1 iex> Keyword.get_lazy(keyword, :b, fun) :result """ @spec get_lazy(t, key, (() -> value)) :: value def get_lazy(keywords, key, fun) when is_list(keywords) and is_atom(key) and is_function(fun, 0) do case :lists.keyfind(key, 1, keywords) do {^key, value} -> value false -> fun.() end end @doc """ Gets the value from `key` and updates it, all in one pass. This `fun` argument receives the value of `key` (or `nil` if `key` is not present) and must return a two-elements tuple: the "get" value (the retrieved value, which can be operated on before being returned) and the new value to be stored under `key`. The returned value is a tuple with the "get" value returned by `fun` and a new keyword list with the updated value under `key`. ## Examples iex> Keyword.get_and_update [a: 1], :a, fn(current_value) -> ...> {current_value, "new value!"} ...> end {1, [a: "new value!"]} """ @spec get_and_update(t, key, (value -> {value, value})) :: {value, t} def get_and_update(keywords, key, fun) when is_list(keywords) and is_atom(key), do: get_and_update(keywords, [], key, fun) defp get_and_update([{key, value}|t], acc, key, fun) do {get, new_value} = fun.(value) {get, :lists.reverse(acc, [{key, new_value}|t])} end defp get_and_update([h|t], acc, key, fun), do: get_and_update(t, [h|acc], key, fun) defp get_and_update([], acc, key, fun) do {get, update} = fun.(nil) {get, [{key, update}|:lists.reverse(acc)]} end @doc """ Fetches the value for a specific `key` and returns it in a tuple. If the `key` does not exist, returns `:error`. ## Examples iex> Keyword.fetch([a: 1], :a) {:ok, 1} iex> Keyword.fetch([a: 1], :b) :error """ @spec fetch(t, key) :: {:ok, value} | :error def fetch(keywords, key) when is_list(keywords) and is_atom(key) do case :lists.keyfind(key, 1, keywords) do {^key, value} -> {:ok, value} false -> :error end end @doc """ Fetches the value for specific `key`. If `key` does not exist, a `KeyError` is raised. ## Examples iex> Keyword.fetch!([a: 1], :a) 1 iex> Keyword.fetch!([a: 1], :b) ** (KeyError) key :b not found in: [a: 1] """ @spec fetch!(t, key) :: value | no_return def fetch!(keywords, key) when is_list(keywords) and is_atom(key) do case :lists.keyfind(key, 1, keywords) do {^key, value} -> value false -> raise(KeyError, key: key, term: keywords) end end @doc """ Gets all values for a specific `key`. ## Examples iex> Keyword.get_values([a: 1, a: 2], :a) [1, 2] """ @spec get_values(t, key) :: [value] def get_values(keywords, key) when is_list(keywords) and is_atom(key) do fun = fn {k, v} when k === key -> {true, v} {_, _} -> false end :lists.filtermap(fun, keywords) end @doc """ Returns all keys from the keyword list. Duplicated keys appear duplicated in the final list of keys. ## Examples iex> Keyword.keys([a: 1, b: 2]) [:a, :b] iex> Keyword.keys([a: 1, b: 2, a: 3]) [:a, :b, :a] """ @spec keys(t) :: [key] def keys(keywords) when is_list(keywords) do :lists.map(fn {k, _} -> k end, keywords) end @doc """ Returns all values from the keyword list. ## Examples iex> Keyword.values([a: 1, b: 2]) [1, 2] """ @spec values(t) :: [value] def values(keywords) when is_list(keywords) do :lists.map(fn {_, v} -> v end, keywords) end @doc """ Deletes the entries in the keyword list for a `key` with `value`. If no `key` with `value` exists, returns the keyword list unchanged. ## Examples iex> Keyword.delete([a: 1, b: 2], :a, 1) [b: 2] iex> Keyword.delete([a: 1, b: 2, a: 3], :a, 3) [a: 1, b: 2] iex> Keyword.delete([b: 2], :a, 5) [b: 2] """ @spec delete(t, key, value) :: t def delete(keywords, key, value) when is_list(keywords) and is_atom(key) do :lists.filter(fn {k, v} -> k != key or v != value end, keywords) end @doc """ Deletes the entries in the keyword list for a specific `key`. If the `key` does not exist, returns the keyword list unchanged. Use `delete_first/2` to delete just the first entry in case of duplicated keys. ## Examples iex> Keyword.delete([a: 1, b: 2], :a) [b: 2] iex> Keyword.delete([a: 1, b: 2, a: 3], :a) [b: 2] iex> Keyword.delete([b: 2], :a) [b: 2] """ @spec delete(t, key) :: t def delete(keywords, key) when is_list(keywords) and is_atom(key) do :lists.filter(fn {k, _} -> k != key end, keywords) end @doc """ Deletes the first entry in the keyword list for a specific `key`. If the `key` does not exist, returns the keyword list unchanged. ## Examples iex> Keyword.delete_first([a: 1, b: 2, a: 3], :a) [b: 2, a: 3] iex> Keyword.delete_first([b: 2], :a) [b: 2] """ @spec delete_first(t, key) :: t def delete_first(keywords, key) when is_list(keywords) and is_atom(key) do :lists.keydelete(key, 1, keywords) end @doc """ Puts the given `value` under `key`. If a previous value is already stored, all entries are removed and the value is overridden. ## Examples iex> Keyword.put([a: 1, b: 2], :a, 3) [a: 3, b: 2] iex> Keyword.put([a: 1, b: 2, a: 4], :a, 3) [a: 3, b: 2] """ @spec put(t, key, value) :: t def put(keywords, key, value) when is_list(keywords) and is_atom(key) do [{key, value}|delete(keywords, key)] end @doc """ Evaluates `fun` and puts the result under `key` in keyword list unless `key` is already present. This is useful if the value is very expensive to calculate or generally difficult to set-up and tear-down again. ## Examples iex> keyword = [a: 1] iex> fun = fn -> ...> # some expensive operation here ...> 3 ...> end iex> Keyword.put_new_lazy(keyword, :a, fun) [a: 1] iex> Keyword.put_new_lazy(keyword, :b, fun) [b: 3, a: 1] """ @spec put_new_lazy(t, key, (() -> value)) :: t def put_new_lazy(keywords, key, fun) when is_list(keywords) and is_atom(key) and is_function(fun, 0) do case :lists.keyfind(key, 1, keywords) do {^key, _} -> keywords false -> [{key, fun.()}|keywords] end end @doc """ Puts the given `value` under `key` unless the entry `key` already exists. ## Examples iex> Keyword.put_new([a: 1], :b, 2) [b: 2, a: 1] iex> Keyword.put_new([a: 1, b: 2], :a, 3) [a: 1, b: 2] """ @spec put_new(t, key, value) :: t def put_new(keywords, key, value) when is_list(keywords) and is_atom(key) do case :lists.keyfind(key, 1, keywords) do {^key, _} -> keywords false -> [{key, value}|keywords] end end @doc """ Checks if two keywords are equal. Two keywords are considered to be equal if they contain the same keys and those keys contain the same values. ## Examples iex> Keyword.equal?([a: 1, b: 2], [b: 2, a: 1]) true """ @spec equal?(t, t) :: boolean def equal?(left, right) when is_list(left) and is_list(right) do :lists.sort(left) == :lists.sort(right) end @doc """ Merges two keyword lists into one. If they have duplicated keys, the one given in the second argument wins. ## Examples iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4]) [a: 3, d: 4, b: 2] """ @spec merge(t, t) :: t def merge(keywords1, keywords2) when is_list(keywords1) and is_list(keywords2) do fun = fn {k, _v} -> not has_key?(keywords2, k) end keywords2 ++ :lists.filter(fun, keywords1) end @doc """ Merges two keyword lists into one. If they have duplicated keys, the given function is invoked to solve conflicts. ## Examples iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4], fn (_k, v1, v2) -> ...> v1 + v2 ...> end) [a: 4, b: 2, d: 4] """ @spec merge(t, t, (key, value, value -> value)) :: t def merge(keywords1, keywords2, fun) when is_list(keywords1) and is_list(keywords2) do do_merge(keywords2, keywords1, fun) end defp do_merge([{k, v2}|t], acc, fun) do do_merge t, update(acc, k, v2, fn(v1) -> fun.(k, v1, v2) end), fun end defp do_merge([], acc, _fun) do acc end @doc """ Returns whether a given `key` exists in the given `keywords`. ## Examples iex> Keyword.has_key?([a: 1], :a) true iex> Keyword.has_key?([a: 1], :b) false """ @spec has_key?(t, key) :: boolean def has_key?(keywords, key) when is_list(keywords) and is_atom(key) do :lists.keymember(key, 1, keywords) end @doc """ Updates the `key` with the given function. If the `key` does not exist, raises `KeyError`. If there are duplicated keys, they are all removed and only the first one is updated. ## Examples iex> Keyword.update!([a: 1], :a, &(&1 * 2)) [a: 2] iex> Keyword.update!([a: 1], :b, &(&1 * 2)) ** (KeyError) key :b not found in: [a: 1] """ @spec update!(t, key, (value -> value)) :: t | no_return def update!(keywords, key, fun) do update!(keywords, key, fun, keywords) end defp update!([{key, value}|keywords], key, fun, _dict) do [{key, fun.(value)}|delete(keywords, key)] end defp update!([{_, _} = e|keywords], key, fun, dict) do [e|update!(keywords, key, fun, dict)] end defp update!([], key, _fun, dict) when is_atom(key) do raise(KeyError, key: key, term: dict) end @doc """ Updates the `key` in `keywords` with the given function. If the `key` does not exist, inserts the given `initial` value. If there are duplicated keys, they are all removed and only the first one is updated. ## Examples iex> Keyword.update([a: 1], :a, 13, &(&1 * 2)) [a: 2] iex> Keyword.update([a: 1], :b, 11, &(&1 * 2)) [a: 1, b: 11] """ @spec update(t, key, value, (value -> value)) :: t def update(keywords, key, initial, fun) def update([{key, value}|keywords], key, _initial, fun) do [{key, fun.(value)}|delete(keywords, key)] end def update([{_, _} = e|keywords], key, initial, fun) do [e|update(keywords, key, initial, fun)] end def update([], key, initial, _fun) when is_atom(key) do [{key, initial}] end @doc """ Takes all entries corresponding to the given keys and extracts them into a separate keyword list. Returns a tuple with the new list and the old list with removed keys. Keys for which there are no entires in the keyword list are ignored. Entries with duplicated keys end up in the same keyword list. ## Examples iex> d = [a: 1, b: 2, c: 3, d: 4] iex> Keyword.split(d, [:a, :c, :e]) {[a: 1, c: 3], [b: 2, d: 4]} iex> d = [a: 1, b: 2, c: 3, d: 4, a: 5] iex> Keyword.split(d, [:a, :c, :e]) {[a: 1, c: 3, a: 5], [b: 2, d: 4]} """ def split(keywords, keys) when is_list(keywords) do fun = fn {k, v}, {take, drop} -> case k in keys do true -> {[{k, v}|take], drop} false -> {take, [{k, v}|drop]} end end acc = {[], []} {take, drop} = :lists.foldl(fun, acc, keywords) {:lists.reverse(take), :lists.reverse(drop)} end @doc """ Takes all entries corresponding to the given keys and returns them in a new keyword list. Duplicated keys are preserved in the new keyword list. ## Examples iex> d = [a: 1, b: 2, c: 3, d: 4] iex> Keyword.take(d, [:a, :c, :e]) [a: 1, c: 3] iex> d = [a: 1, b: 2, c: 3, d: 4, a: 5] iex> Keyword.take(d, [:a, :c, :e]) [a: 1, c: 3, a: 5] """ def take(keywords, keys) when is_list(keywords) do :lists.filter(fn {k, _} -> k in keys end, keywords) end @doc """ Drops the given keys from the keyword list. Duplicated keys are preserved in the new keyword list. ## Examples iex> d = [a: 1, b: 2, c: 3, d: 4] iex> Keyword.drop(d, [:b, :d]) [a: 1, c: 3] iex> d = [a: 1, b: 2, b: 3, c: 3, d: 4, a: 5] iex> Keyword.drop(d, [:b, :d]) [a: 1, c: 3, a: 5] """ def drop(keywords, keys) when is_list(keywords) do :lists.filter(fn {k, _} -> not k in keys end, keywords) end @doc """ Returns the first value associated with `key` in the keyword list as well as the keyword list without `key`. All duplicated keys are removed. See `pop_first/3` for removing only the first entry. ## Examples iex> Keyword.pop [a: 1], :a {1, []} iex> Keyword.pop [a: 1], :b {nil, [a: 1]} iex> Keyword.pop [a: 1], :b, 3 {3, [a: 1]} iex> Keyword.pop [a: 1, a: 2], :a {1, []} """ @spec pop(t, key, value) :: {value, t} def pop(keywords, key, default \\ nil) when is_list(keywords) do case fetch(keywords, key) do {:ok, value} -> {value, delete(keywords, key)} :error -> {default, keywords} end end @doc """ Returns the first value associated with `key` in the keyword list as well as the keyword list without `key`. This is useful if the default value is very expensive to calculate or generally difficult to set-up and tear-down again. All duplicated keys are removed. See `pop_first/3` for removing only the first entry. ## Examples iex> keyword = [a: 1] iex> fun = fn -> ...> # some expensive operation here ...> :result ...> end iex> Keyword.pop_lazy(keyword, :a, fun) {1, []} iex> Keyword.pop_lazy(keyword, :b, fun) {:result, [a: 1]} """ @spec pop_lazy(t, key, (() -> value)) :: {value, t} def pop_lazy(keywords, key, fun) when is_list(keywords) and is_function(fun, 0) do case fetch(keywords, key) do {:ok, value} -> {value, delete(keywords, key)} :error -> {fun.(), keywords} end end @doc """ Returns the first value associated with `key` in the keyword list as well as the keyword list without that particular occurrence of `key`. Duplicated keys are not removed. ## Examples iex> Keyword.pop_first [a: 1], :a {1, []} iex> Keyword.pop_first [a: 1], :b {nil, [a: 1]} iex> Keyword.pop_first [a: 1], :b, 3 {3, [a: 1]} iex> Keyword.pop_first [a: 1, a: 2], :a {1, [a: 2]} """ @spec pop_first(t, key, value) :: {value, t} def pop_first(keywords, key, default \\ nil) when is_list(keywords) do case :lists.keytake(key, 1, keywords) do {:value, {^key, value}, rest} -> {value, rest} false -> {default, keywords} end end # Dict callbacks @doc false def size(keyword) do length(keyword) end @doc false def to_list(keyword) do keyword end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/list.ex000066400000000000000000000350641254730255300212460ustar00rootroot00000000000000defmodule List do @moduledoc """ Implements functions that only make sense for lists and cannot be part of the Enum protocol. In general, favor using the Enum API instead of List. Some functions in this module expect an index. Index access for list is linear. Negative indexes are also supported but they imply the list will be iterated twice, one to calculate the proper index and another to the operation. A decision was taken to delegate most functions to Erlang's standard library but follow Elixir's convention of receiving the target (in this case, a list) as the first argument. """ @compile :inline_list_funcs @doc """ Deletes the given item from the list. Returns a list without the item. If the item occurs more than once in the list, just the first occurrence is removed. ## Examples iex> List.delete([1, 2, 3], 1) [2, 3] iex> List.delete([1, 2, 2, 3], 2) [1, 2, 3] """ @spec delete(list, any) :: list def delete(list, item) do :lists.delete(item, list) end @doc """ Duplicates the given element `n` times in a list. ## Examples iex> List.duplicate("hello", 3) ["hello", "hello", "hello"] iex> List.duplicate([1, 2], 2) [[1, 2], [1, 2]] """ @spec duplicate(elem, non_neg_integer) :: [elem] when elem: var def duplicate(elem, n) do :lists.duplicate(n, elem) end @doc """ Flattens the given `list` of nested lists. ## Examples iex> List.flatten([1, [[2], 3]]) [1, 2, 3] """ @spec flatten(deep_list) :: list when deep_list: [any | deep_list] def flatten(list) do :lists.flatten(list) end @doc """ Flattens the given `list` of nested lists. The list `tail` will be added at the end of the flattened list. ## Examples iex> List.flatten([1, [[2], 3]], [4, 5]) [1, 2, 3, 4, 5] """ @spec flatten(deep_list, [elem]) :: [elem] when elem: var, deep_list: [elem | deep_list] def flatten(list, tail) do :lists.flatten(list, tail) end @doc """ Folds (reduces) the given list from the left with a function. Requires an accumulator. ## Examples iex> List.foldl([5, 5], 10, fn (x, acc) -> x + acc end) 20 iex> List.foldl([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end) 2 """ @spec foldl([elem], acc, (elem, acc -> acc)) :: acc when elem: var, acc: var def foldl(list, acc, function) when is_list(list) and is_function(function) do :lists.foldl(function, acc, list) end @doc """ Folds (reduces) the given list from the right with a function. Requires an accumulator. ## Examples iex> List.foldr([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end) -2 """ @spec foldr([elem], acc, (elem, acc -> acc)) :: acc when elem: var, acc: var def foldr(list, acc, function) when is_list(list) and is_function(function) do :lists.foldr(function, acc, list) end @doc """ Returns the first element in `list` or `nil` if `list` is empty. ## Examples iex> List.first([]) nil iex> List.first([1]) 1 iex> List.first([1, 2, 3]) 1 """ @spec first([elem]) :: nil | elem when elem: var def first([]), do: nil def first([h|_]), do: h @doc """ Returns the last element in `list` or `nil` if `list` is empty. ## Examples iex> List.last([]) nil iex> List.last([1]) 1 iex> List.last([1, 2, 3]) 3 """ @spec last([elem]) :: nil | elem when elem: var def last([]), do: nil def last([h]), do: h def last([_|t]), do: last(t) @doc """ Receives a list of tuples and returns the first tuple where the item at `position` in the tuple matches the given `key`. ## Examples iex> List.keyfind([a: 1, b: 2], :a, 0) {:a, 1} iex> List.keyfind([a: 1, b: 2], 2, 1) {:b, 2} iex> List.keyfind([a: 1, b: 2], :c, 0) nil """ @spec keyfind([tuple], any, non_neg_integer, any) :: any def keyfind(list, key, position, default \\ nil) do :lists.keyfind(key, position + 1, list) || default end @doc """ Receives a list of tuples and returns `true` if there is a tuple where the item at `position` in the tuple matches the given `key`. ## Examples iex> List.keymember?([a: 1, b: 2], :a, 0) true iex> List.keymember?([a: 1, b: 2], 2, 1) true iex> List.keymember?([a: 1, b: 2], :c, 0) false """ @spec keymember?([tuple], any, non_neg_integer) :: any def keymember?(list, key, position) do :lists.keymember(key, position + 1, list) end @doc """ Receives a list of tuples and replaces the item identified by `key` at `position` if it exists. ## Examples iex> List.keyreplace([a: 1, b: 2], :a, 0, {:a, 3}) [a: 3, b: 2] """ @spec keyreplace([tuple], any, non_neg_integer, tuple) :: [tuple] def keyreplace(list, key, position, new_tuple) do :lists.keyreplace(key, position + 1, list, new_tuple) end @doc """ Receives a list of tuples and sorts the items at `position` of the tuples. The sort is stable. ## Examples iex> List.keysort([a: 5, b: 1, c: 3], 1) [b: 1, c: 3, a: 5] iex> List.keysort([a: 5, c: 1, b: 3], 0) [a: 5, b: 3, c: 1] """ @spec keysort([tuple], non_neg_integer) :: [tuple] def keysort(list, position) do :lists.keysort(position + 1, list) end @doc """ Receives a list of tuples and replaces the item identified by `key` at `position`. If the item does not exist, it is added to the end of the list. ## Examples iex> List.keystore([a: 1, b: 2], :a, 0, {:a, 3}) [a: 3, b: 2] iex> List.keystore([a: 1, b: 2], :c, 0, {:c, 3}) [a: 1, b: 2, c: 3] """ @spec keystore([tuple], any, non_neg_integer, tuple) :: [tuple, ...] def keystore(list, key, position, new_tuple) do :lists.keystore(key, position + 1, list, new_tuple) end @doc """ Receives a list of tuples and deletes the first tuple where the item at `position` matches the given `key`. Returns the new list. ## Examples iex> List.keydelete([a: 1, b: 2], :a, 0) [b: 2] iex> List.keydelete([a: 1, b: 2], 2, 1) [a: 1] iex> List.keydelete([a: 1, b: 2], :c, 0) [a: 1, b: 2] """ @spec keydelete([tuple], any, non_neg_integer) :: [tuple] def keydelete(list, key, position) do :lists.keydelete(key, position + 1, list) end @doc """ Wraps the argument in a list. If the argument is already a list, returns the list. If the argument is `nil`, returns an empty list. ## Examples iex> List.wrap("hello") ["hello"] iex> List.wrap([1, 2, 3]) [1, 2, 3] iex> List.wrap(nil) [] """ @spec wrap(list | any) :: list def wrap(list) when is_list(list) do list end def wrap(nil) do [] end def wrap(other) do [other] end @doc """ Zips corresponding elements from each list in `list_of_lists`. The zipping finishes as soon as any list terminates. ## Examples iex> List.zip([[1, 2], [3, 4], [5, 6]]) [{1, 3, 5}, {2, 4, 6}] iex> List.zip([[1, 2], [3], [5, 6]]) [{1, 3, 5}] """ @spec zip([list]) :: [tuple] def zip([]), do: [] def zip(list_of_lists) when is_list(list_of_lists) do do_zip(list_of_lists, []) end @doc """ Returns a list with `value` inserted at the specified `index`. Note that `index` is capped at the list length. Negative indices indicate an offset from the end of the list. ## Examples iex> List.insert_at([1, 2, 3, 4], 2, 0) [1, 2, 0, 3, 4] iex> List.insert_at([1, 2, 3], 10, 0) [1, 2, 3, 0] iex> List.insert_at([1, 2, 3], -1, 0) [1, 2, 3, 0] iex> List.insert_at([1, 2, 3], -10, 0) [0, 1, 2, 3] """ @spec insert_at(list, integer, any) :: list def insert_at(list, index, value) do if index < 0 do do_insert_at(list, length(list) + index + 1, value) else do_insert_at(list, index, value) end end @doc """ Returns a list with a replaced value at the specified `index`. Negative indices indicate an offset from the end of the list. If `index` is out of bounds, the original `list` is returned. ## Examples iex> List.replace_at([1, 2, 3], 0, 0) [0, 2, 3] iex> List.replace_at([1, 2, 3], 10, 0) [1, 2, 3] iex> List.replace_at([1, 2, 3], -1, 0) [1, 2, 0] iex> List.replace_at([1, 2, 3], -10, 0) [1, 2, 3] """ @spec replace_at(list, integer, any) :: list def replace_at(list, index, value) do if index < 0 do do_replace_at(list, length(list) + index, value) else do_replace_at(list, index, value) end end @doc """ Returns a list with an updated value at the specified `index`. Negative indices indicate an offset from the end of the list. If `index` is out of bounds, the original `list` is returned. ## Examples iex> List.update_at([1, 2, 3], 0, &(&1 + 10)) [11, 2, 3] iex> List.update_at([1, 2, 3], 10, &(&1 + 10)) [1, 2, 3] iex> List.update_at([1, 2, 3], -1, &(&1 + 10)) [1, 2, 13] iex> List.update_at([1, 2, 3], -10, &(&1 + 10)) [1, 2, 3] """ @spec update_at([elem], integer, (elem -> any)) :: list when elem: var def update_at(list, index, fun) do if index < 0 do do_update_at(list, length(list) + index, fun) else do_update_at(list, index, fun) end end @doc """ Produces a new list by removing the value at the specified `index`. Negative indices indicate an offset from the end of the list. If `index` is out of bounds, the original `list` is returned. ## Examples iex> List.delete_at([1, 2, 3], 0) [2, 3] iex List.delete_at([1, 2, 3], 10) [1, 2, 3] iex> List.delete_at([1, 2, 3], -1) [1, 2] """ @spec delete_at(list, integer) :: list def delete_at(list, index) do if index < 0 do do_delete_at(list, length(list) + index) else do_delete_at(list, index) end end @doc """ Converts a char list to an atom. Currently Elixir does not support conversions from char lists which contains Unicode codepoints greater than 0xFF. Inlined by the compiler. ## Examples iex> List.to_atom('elixir') :elixir """ @spec to_atom(char_list) :: atom def to_atom(char_list) do :erlang.list_to_atom(char_list) end @doc """ Converts a char list to an existing atom. Raises an `ArguementError` if the atom does not exist. Currently Elixir does not support conversions from char lists which contains Unicode codepoints greater than 0xFF. Inlined by the compiler. ## Examples iex> :barney iex> List.to_existing_atom('barney') :barney iex> List.to_existing_atom('fred') ** (ArgumentError) argument error :erlang.list_to_existing_atom('fred') """ @spec to_existing_atom(char_list) :: atom def to_existing_atom(char_list) do :erlang.list_to_existing_atom(char_list) end @doc """ Returns the float whose text representation is `char_list`. Inlined by the compiler. ## Examples iex> List.to_float('2.2017764e+0') 2.2017764 """ @spec to_float(char_list) :: float def to_float(char_list) do :erlang.list_to_float(char_list) end @doc """ Returns an integer whose text representation is `char_list`. Inlined by the compiler. ## Examples iex> List.to_integer('123') 123 """ @spec to_integer(char_list) :: integer def to_integer(char_list) do :erlang.list_to_integer(char_list) end @doc """ Returns an integer whose text representation is `char_list` in base `base`. Inlined by the compiler. ## Examples iex> List.to_integer('3FF', 16) 1023 """ @spec to_integer(char_list, 2..36) :: integer def to_integer(char_list, base) do :erlang.list_to_integer(char_list, base) end @doc """ Converts a list to a tuple. Inlined by the compiler. ## Examples iex> List.to_tuple([:share, [:elixir, 163]]) {:share, [:elixir, 163]} """ @spec to_tuple(list) :: tuple def to_tuple(list) do :erlang.list_to_tuple(list) end @doc """ Converts a list of integers representing codepoints, lists or strings into a string. Notice that this function expects a list of integers representing UTF-8 codepoints. If you have a list of bytes, you must instead use [the `:binary` module](http://erlang.org/doc/man/binary.html). ## Examples iex> List.to_string([0x00E6, 0x00DF]) "æß" iex> List.to_string([0x0061, "bc"]) "abc" """ @spec to_string(:unicode.charlist) :: String.t def to_string(list) when is_list(list) do case :unicode.characters_to_binary(list) do result when is_binary(result) -> result {:error, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :invalid {:incomplete, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :incomplete end end ## Helpers # replace_at defp do_replace_at([], _index, _value) do [] end defp do_replace_at(list, index, _value) when index < 0 do list end defp do_replace_at([_old|rest], 0, value) do [ value | rest ] end defp do_replace_at([h|t], index, value) do [ h | do_replace_at(t, index - 1, value) ] end # insert_at defp do_insert_at([], _index, value) do [ value ] end defp do_insert_at(list, index, value) when index <= 0 do [ value | list ] end defp do_insert_at([h|t], index, value) do [ h | do_insert_at(t, index - 1, value) ] end # update_at defp do_update_at([value|list], 0, fun) do [ fun.(value) | list ] end defp do_update_at(list, index, _fun) when index < 0 do list end defp do_update_at([h|t], index, fun) do [ h | do_update_at(t, index - 1, fun) ] end defp do_update_at([], _index, _fun) do [] end # delete_at defp do_delete_at([], _index) do [] end defp do_delete_at([_|t], 0) do t end defp do_delete_at(list, index) when index < 0 do list end defp do_delete_at([h|t], index) do [h | do_delete_at(t, index-1)] end # zip defp do_zip(list, acc) do converter = fn x, acc -> do_zip_each(to_list(x), acc) end {mlist, heads} = :lists.mapfoldl converter, [], list case heads do nil -> :lists.reverse acc _ -> do_zip mlist, [:erlang.list_to_tuple(:lists.reverse(heads))|acc] end end defp do_zip_each(_, nil) do {nil, nil} end defp do_zip_each([h|t], acc) do {t, [h|acc]} end defp do_zip_each([], _) do {nil, nil} end defp to_list(tuple) when is_tuple(tuple), do: Tuple.to_list(tuple) defp to_list(list) when is_list(list), do: list end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/list/000077500000000000000000000000001254730255300207005ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/list/chars.ex000066400000000000000000000024671254730255300223470ustar00rootroot00000000000000defprotocol List.Chars do @moduledoc ~S""" The List.Chars protocol is responsible for converting a structure to a list (only if applicable). The only function required to be implemented is `to_char_list` which does the conversion. The `to_char_list` function automatically imported by Kernel invokes this protocol. """ def to_char_list(thing) end defimpl List.Chars, for: Atom do def to_char_list(atom), do: Atom.to_char_list(atom) end defimpl List.Chars, for: BitString do @doc """ Returns the given binary converted to a char list. """ def to_char_list(thing) when is_binary(thing) do String.to_char_list(thing) end def to_char_list(thing) do raise Protocol.UndefinedError, protocol: @protocol, value: thing, description: "cannot convert a bitstring to a char list" end end defimpl List.Chars, for: List do def to_char_list(list), do: list end defimpl List.Chars, for: Integer do def to_char_list(thing) do Integer.to_char_list(thing) end end defimpl List.Chars, for: Float do @digits 20 @limit :math.pow(10, @digits) def to_char_list(thing) when thing > @limit do Float.to_char_list(thing, scientific: @digits) end def to_char_list(thing) do Float.to_char_list(thing, compact: true, decimals: @digits) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/macro.ex000066400000000000000000000716141254730255300213750ustar00rootroot00000000000000import Kernel, except: [to_string: 1] defmodule Macro do @moduledoc """ Conveniences for working with macros. """ @typedoc "Abstract Syntax Tree (AST)" @type t :: expr | {t, t} | atom | number | binary | pid | fun | [t] @typedoc "Expr node (remaining ones are literals)" @type expr :: {expr | atom, Keyword.t, atom | [t]} @binary_ops [:===, :!==, :==, :!=, :<=, :>=, :&&, :||, :<>, :++, :--, :\\, :::, :<-, :.., :|>, :=~, :<, :>, :->, :+, :-, :*, :/, :=, :|, :., :and, :or, :when, :in, :~>>, :<<~, :~>, :<~, :<~>, :<|>, :<<<, :>>>, :|||, :&&&, :^^^, :~~~] @doc false defmacro binary_ops, do: @binary_ops @unary_ops [:!, :@, :^, :not, :+, :-, :~~~, :&] @doc false defmacro unary_ops, do: @unary_ops @spec binary_op_props(atom) :: {:left | :right, precedence :: integer} defp binary_op_props(o) do case o do o when o in [:<-, :\\] -> {:left, 40} :when -> {:right, 50} ::: -> {:right, 60} :| -> {:right, 70} := -> {:right, 90} o when o in [:||, :|||, :or] -> {:left, 130} o when o in [:&&, :&&&, :and] -> {:left, 140} o when o in [:==, :!=, :=~, :===, :!==] -> {:left, 150} o when o in [:<, :<=, :>=, :>] -> {:left, 160} o when o in [:|>, :<<<, :>>>, :<~, :~>, :<<~, :~>>, :<~>, :<|>] -> {:left, 170} :in -> {:left, 180} o when o in [:++, :--, :.., :<>] -> {:right, 200} o when o in [:+, :-] -> {:left, 210} o when o in [:*, :/] -> {:left, 220} :^^^ -> {:left, 250} :. -> {:left, 310} end end @doc """ Breaks a pipeline expression into a list. Raises if the pipeline is ill-formed. """ @spec unpipe(Macro.t) :: [Macro.t] def unpipe(expr) do :lists.reverse(unpipe(expr, [])) end defp unpipe({:|>, _, [left, right]}, acc) do unpipe(right, unpipe(left, acc)) end defp unpipe(other, acc) do [{other, 0}|acc] end @doc """ Pipes `expr` into the `call_args` at the given `position`. """ @spec pipe(Macro.t, Macro.t, integer) :: Macro.t | no_return def pipe(expr, call_args, position) def pipe(expr, {:&, _, _} = call_args, _integer) do bad_pipe(expr, call_args) end def pipe(expr, {call, line, atom}, integer) when is_atom(atom) do {call, line, List.insert_at([], integer, expr)} end def pipe(expr, {call, line, args}, integer) when is_list(args) do {call, line, List.insert_at(args, integer, expr)} end def pipe(expr, call_args, _integer) do bad_pipe(expr, call_args) end defp bad_pipe(expr, call_args) do raise ArgumentError, "cannot pipe #{to_string expr} into #{to_string call_args}, " <> "can only pipe into local calls foo(), remote calls Foo.bar() or anonymous functions calls foo.()" end @doc """ Applies the given function to the node metadata if it contains one. This is often useful when used with `Macro.prewalk/1` to remove information like lines and hygienic counters from the expression for either storage or comparison. ## Examples iex> quoted = quote line: 10, do: sample() {:sample, [line: 10], []} iex> Macro.update_meta(quoted, &Keyword.delete(&1, :line)) {:sample, [], []} """ @spec update_meta(t, (Keyword.t -> Keyword.t)) :: t def update_meta(quoted, fun) def update_meta({left, meta, right}, fun) when is_list(meta) do {left, fun.(meta), right} end def update_meta(other, _fun) do other end @doc """ Generates an AST node representing the variable given by the atoms `var` and `context`. ## Examples In order to build a variable, a context is expected. Most of the times, in order to preserve hygiene, the context must be `__MODULE__`: iex> Macro.var(:foo, __MODULE__) {:foo, [], __MODULE__} However, if there is a need to access the user variable, nil can be given: iex> Macro.var(:foo, nil) {:foo, [], nil} """ @spec var(var, context) :: {var, [], context} when var: atom, context: atom def var(var, context) when is_atom(var) and is_atom(context) do {var, [], context} end @doc """ Performs a depth-first, pre-order traversal of quoted expressions. """ @spec prewalk(t, (t -> t)) :: t def prewalk(ast, fun) when is_function(fun, 1) do elem(prewalk(ast, nil, fn x, nil -> {fun.(x), nil} end), 0) end @doc """ Performs a depth-first, pre-order traversal of quoted expressions using an accumulator. """ @spec prewalk(t, any, (t, any -> {t, any})) :: {t, any} def prewalk(ast, acc, fun) when is_function(fun, 2) do {ast, acc} = fun.(ast, acc) do_prewalk(ast, acc, fun) end defp do_prewalk({form, meta, args}, acc, fun) do unless is_atom(form) do {form, acc} = fun.(form, acc) {form, acc} = do_prewalk(form, acc, fun) end unless is_atom(args) do {args, acc} = Enum.map_reduce(args, acc, fn x, acc -> {x, acc} = fun.(x, acc) do_prewalk(x, acc, fun) end) end {{form, meta, args}, acc} end defp do_prewalk({left, right}, acc, fun) do {left, acc} = fun.(left, acc) {left, acc} = do_prewalk(left, acc, fun) {right, acc} = fun.(right, acc) {right, acc} = do_prewalk(right, acc, fun) {{left, right}, acc} end defp do_prewalk(list, acc, fun) when is_list(list) do Enum.map_reduce(list, acc, fn x, acc -> {x, acc} = fun.(x, acc) do_prewalk(x, acc, fun) end) end defp do_prewalk(x, acc, _fun) do {x, acc} end @doc """ Performs a depth-first, post-order traversal of quoted expressions. """ @spec postwalk(t, (t -> t)) :: t def postwalk(ast, fun) when is_function(fun, 1) do elem(postwalk(ast, nil, fn x, nil -> {fun.(x), nil} end), 0) end @doc """ Performs a depth-first, post-order traversal of quoted expressions using an accumulator. """ @spec postwalk(t, any, (t, any -> {t, any})) :: {t, any} def postwalk(ast, acc, fun) when is_function(fun, 2) do do_postwalk(ast, acc, fun) end defp do_postwalk({form, meta, args}, acc, fun) do unless is_atom(form) do {form, acc} = do_postwalk(form, acc, fun) end unless is_atom(args) do {args, acc} = Enum.map_reduce(args, acc, &do_postwalk(&1, &2, fun)) end fun.({form, meta, args}, acc) end defp do_postwalk({left, right}, acc, fun) do {left, acc} = do_postwalk(left, acc, fun) {right, acc} = do_postwalk(right, acc, fun) fun.({left, right}, acc) end defp do_postwalk(list, acc, fun) when is_list(list) do {list, acc} = Enum.map_reduce(list, acc, &do_postwalk(&1, &2, fun)) fun.(list, acc) end defp do_postwalk(x, acc, fun) do fun.(x, acc) end @doc """ Decomposes a local or remote call into its remote part (when provided), function name and argument list. Returns `:error` when an invalid call syntax is provided. ## Examples iex> Macro.decompose_call(quote do: foo) {:foo, []} iex> Macro.decompose_call(quote do: foo()) {:foo, []} iex> Macro.decompose_call(quote do: foo(1, 2, 3)) {:foo, [1, 2, 3]} iex> Macro.decompose_call(quote do: Elixir.M.foo(1, 2, 3)) {{:__aliases__, [], [:Elixir, :M]}, :foo, [1, 2, 3]} iex> Macro.decompose_call(quote do: 42) :error """ @spec decompose_call(Macro.t) :: {atom, [Macro.t]} | {Macro.t, atom, [Macro.t]} | :error def decompose_call(ast) def decompose_call({{:., _, [remote, function]}, _, args}) when is_tuple(remote) or is_atom(remote), do: {remote, function, args} def decompose_call({name, _, args}) when is_atom(name) and is_atom(args), do: {name, []} def decompose_call({name, _, args}) when is_atom(name) and is_list(args), do: {name, args} def decompose_call(_), do: :error @doc """ Recursively escapes a value so it can be inserted into a syntax tree. One may pass `unquote: true` to `escape/2` which leaves `unquote` statements unescaped, effectively unquoting the contents on escape. ## Examples iex> Macro.escape(:foo) :foo iex> Macro.escape({:a, :b, :c}) {:{}, [], [:a, :b, :c]} iex> Macro.escape({:unquote, [], [1]}, unquote: true) 1 """ @spec escape(term) :: Macro.t @spec escape(term, Keyword.t) :: Macro.t def escape(expr, opts \\ []) do elem(:elixir_quote.escape(expr, Keyword.get(opts, :unquote, false)), 0) end @doc """ Validates the given expressions are valid quoted expressions. Check the `type:Macro.t` for the specification of a valid quoted expression. """ @spec validate(term) :: :ok | {:error, term} def validate(expr) do find_invalid(expr) || :ok end defp find_invalid({left, right}), do: find_invalid(left) || find_invalid(right) defp find_invalid({left, meta, right}) when is_list(meta) and (is_atom(right) or is_list(right)), do: find_invalid(left) || find_invalid(right) defp find_invalid(list) when is_list(list), do: Enum.find_value(list, &find_invalid/1) defp find_invalid(pid) when is_pid(pid), do: nil defp find_invalid(atom) when is_atom(atom), do: nil defp find_invalid(num) when is_number(num), do: nil defp find_invalid(bin) when is_binary(bin), do: nil defp find_invalid(fun) when is_function(fun) do unless :erlang.fun_info(fun, :env) == {:env, []} and :erlang.fun_info(fun, :type) == {:type, :external} do {:error, fun} end end defp find_invalid(other), do: {:error, other} @doc ~S""" Unescape the given chars. This is the unescaping behaviour used by default in Elixir single- and double-quoted strings. Check `unescape_string/2` for information on how to customize the escaping map. In this setup, Elixir will escape the following: `\0`, `\a`, `\b`, `\d`, `\e`, `\f`, `\n`, `\r`, `\s`, `\t` and `\v`. Unicode codepoints can be given as hexadecimals via `\xNN` and `\x{NN...}` escapes. This function is commonly used on sigil implementations (like `~r`, `~s` and others) which receive a raw, unescaped string. ## Examples iex> Macro.unescape_string("example\\n") "example\n" In the example above, we pass a string with `\n` escaped and return a version with it unescaped. """ @spec unescape_string(String.t) :: String.t def unescape_string(chars) do :elixir_interpolation.unescape_chars(chars) end @doc ~S""" Unescapes the given chars according to the map given. Check `unescape_string/1` if you want to use the same map as Elixir single- and double-quoted strings. ## Map The map must be a function. The function receives an integer representing the codepoint of the character it wants to unescape. Here is the default mapping function implemented by Elixir: def unescape_map(?0), do: ?0 def unescape_map(?a), do: ?\a def unescape_map(?b), do: ?\b def unescape_map(?d), do: ?\d def unescape_map(?e), do: ?\e def unescape_map(?f), do: ?\f def unescape_map(?n), do: ?\n def unescape_map(?r), do: ?\r def unescape_map(?s), do: ?\s def unescape_map(?t), do: ?\t def unescape_map(?v), do: ?\v def unescape_map(?x), do: true def unescape_map(e), do: e If the `unescape_map` function returns `false`. The char is not escaped and `\` is kept in the char list. Hexadecimals will be escaped if the map function returns `true` for `?x`. ## Examples Using the `unescape_map` function defined above is easy: Macro.unescape_string "example\\n", &unescape_map(&1) """ @spec unescape_string(String.t, (non_neg_integer -> non_neg_integer | false)) :: String.t def unescape_string(chars, map) do :elixir_interpolation.unescape_chars(chars, map) end @doc """ Unescapes the given tokens according to the default map. Check `unescape_string/1` and `unescape_string/2` for more information about unescaping. Only tokens that are binaries are unescaped, all others are ignored. This function is useful when implementing your own sigils. Check the implementation of `Kernel.sigil_s/2` for examples. """ @spec unescape_tokens([Macro.t]) :: [Macro.t] def unescape_tokens(tokens) do :elixir_interpolation.unescape_tokens(tokens) end @doc """ Unescapes the given tokens according to the given map. Check `unescape_tokens/1` and `unescape_string/2` for more information. """ @spec unescape_tokens([Macro.t], (non_neg_integer -> non_neg_integer | false)) :: [Macro.t] def unescape_tokens(tokens, map) do :elixir_interpolation.unescape_tokens(tokens, map) end @doc """ Converts the given expression to a binary. ## Examples iex> Macro.to_string(quote do: foo.bar(1, 2, 3)) "foo.bar(1, 2, 3)" """ @spec to_string(Macro.t) :: String.t @spec to_string(Macro.t, (Macro.t, String.t -> String.t)) :: String.t def to_string(tree, fun \\ fn(_ast, string) -> string end) # Variables def to_string({var, _, atom} = ast, fun) when is_atom(atom) do fun.(ast, Atom.to_string(var)) end # Aliases def to_string({:__aliases__, _, refs} = ast, fun) do fun.(ast, Enum.map_join(refs, ".", &call_to_string(&1, fun))) end # Blocks def to_string({:__block__, _, [expr]} = ast, fun) do fun.(ast, to_string(expr, fun)) end def to_string({:__block__, _, _} = ast, fun) do block = adjust_new_lines block_to_string(ast, fun), "\n " fun.(ast, "(\n " <> block <> "\n)") end # Bits containers def to_string({:<<>>, _, args} = ast, fun) do if interpolated?(ast) do fun.(ast, interpolate(ast, fun)) else fun.(ast, case Enum.map_join(args, ", ", &to_string(&1, fun)) do "<" <> rest -> "<< <" <> rest <> " >>" rest -> "<<" <> rest <> ">>" end) end end # Tuple containers def to_string({:{}, _, args} = ast, fun) do tuple = "{" <> Enum.map_join(args, ", ", &to_string(&1, fun)) <> "}" fun.(ast, tuple) end # Map containers def to_string({:%{}, _, args} = ast, fun) do map = "%{" <> map_to_string(args, fun) <> "}" fun.(ast, map) end def to_string({:%, _, [structname, map]} = ast, fun) do {:%{}, _, args} = map struct = "%" <> to_string(structname, fun) <> "{" <> map_to_string(args, fun) <> "}" fun.(ast, struct) end # Fn keyword def to_string({:fn, _, [{:->, _, [_, tuple]}] = arrow} = ast, fun) when not is_tuple(tuple) or elem(tuple, 0) != :__block__ do fun.(ast, "fn " <> arrow_to_string(arrow, fun) <> " end") end def to_string({:fn, _, [{:->, _, _}] = block} = ast, fun) do fun.(ast, "fn " <> block_to_string(block, fun) <> "\nend") end def to_string({:fn, _, block} = ast, fun) do block = adjust_new_lines block_to_string(block, fun), "\n " fun.(ast, "fn\n " <> block <> "\nend") end # left -> right def to_string([{:->, _, _}|_] = ast, fun) do fun.(ast, "(" <> arrow_to_string(ast, fun, true) <> ")") end # left when right def to_string({:when, _, [left, right]} = ast, fun) do if right != [] and Keyword.keyword?(right) do right = kw_list_to_string(right, fun) else right = fun.(ast, op_to_string(right, fun, :when, :right)) end fun.(ast, op_to_string(left, fun, :when, :left) <> " when " <> right) end # Binary ops def to_string({op, _, [left, right]} = ast, fun) when op in unquote(@binary_ops) do fun.(ast, op_to_string(left, fun, op, :left) <> " #{op} " <> op_to_string(right, fun, op, :right)) end # Splat when def to_string({:when, _, args} = ast, fun) do {left, right} = :elixir_utils.split_last(args) fun.(ast, "(" <> Enum.map_join(left, ", ", &to_string(&1, fun)) <> ") when " <> to_string(right, fun)) end # Unary ops def to_string({unary, _, [{binary, _, [_, _]} = arg]} = ast, fun) when unary in unquote(@unary_ops) and binary in unquote(@binary_ops) do fun.(ast, Atom.to_string(unary) <> "(" <> to_string(arg, fun) <> ")") end def to_string({:not, _, [arg]} = ast, fun) do fun.(ast, "not " <> to_string(arg, fun)) end def to_string({op, _, [arg]} = ast, fun) when op in unquote(@unary_ops) do fun.(ast, Atom.to_string(op) <> to_string(arg, fun)) end # Access def to_string({{:., _, [Access, :get]}, _, [left, right]} = ast, fun) do fun.(ast, to_string(left, fun) <> to_string([right], fun)) end # All other calls def to_string({target, _, args} = ast, fun) when is_list(args) do if sigil = sigil_call(ast, fun) do sigil else {list, last} = :elixir_utils.split_last(args) fun.(ast, case kw_blocks?(last) do true -> call_to_string_with_args(target, list, fun) <> kw_blocks_to_string(last, fun) false -> call_to_string_with_args(target, args, fun) end) end end # Two-item tuples def to_string({left, right}, fun) do to_string({:{}, [], [left, right]}, fun) end # Lists def to_string(list, fun) when is_list(list) do fun.(list, cond do list == [] -> "[]" :io_lib.printable_list(list) -> "'" <> Inspect.BitString.escape(IO.chardata_to_string(list), ?') <> "'" Keyword.keyword?(list) -> "[" <> kw_list_to_string(list, fun) <> "]" true -> "[" <> Enum.map_join(list, ", ", &to_string(&1, fun)) <> "]" end) end # All other structures def to_string(other, fun), do: fun.(other, inspect(other, [])) # Block keywords @kw_keywords [:do, :catch, :rescue, :after, :else] defp kw_blocks?([_|_] = kw) do Enum.all?(kw, &match?({x, _} when x in unquote(@kw_keywords), &1)) end defp kw_blocks?(_), do: false # Check if we have an interpolated string. defp interpolated?({:<<>>, _, [_|_] = parts}) do Enum.all?(parts, fn {:::, _, [{{:., _, [Kernel, :to_string]}, _, [_]}, {:binary, _, _}]} -> true binary when is_binary(binary) -> true _ -> false end) end defp interpolated?(_) do false end def interpolate(expr, fun) def interpolate({:<<>>, _, parts}, fun) do parts = Enum.map_join(parts, "", fn {:::, _, [{{:., _, [Kernel, :to_string]}, _, [arg]}, {:binary, _, _}]} -> "\#{" <> to_string(arg, fun) <> "}" binary when is_binary(binary) -> binary = inspect(binary, []) :binary.part(binary, 1, byte_size(binary) - 2) end) <> end defp module_to_string(atom, _fun) when is_atom(atom), do: inspect(atom, []) defp module_to_string(other, fun), do: call_to_string(other, fun) defp sigil_call({func, _, [{:<<>>, _, _} = bin, args]} = ast, fun) when is_list(args) do sigil = case Atom.to_string(func) do <<"sigil_", name>> -> "~" <> <> <> interpolate(bin, fun) <> sigil_args(args, fun) _ -> nil end fun.(ast, sigil) end defp sigil_call(_other, _fun) do nil end defp sigil_args([], _fun), do: "" defp sigil_args(args, fun), do: fun.(args, List.to_string(args)) defp call_to_string(atom, _fun) when is_atom(atom), do: Atom.to_string(atom) defp call_to_string({:., _, [arg]}, fun), do: module_to_string(arg, fun) <> "." defp call_to_string({:., _, [left, right]}, fun), do: module_to_string(left, fun) <> "." <> call_to_string(right, fun) defp call_to_string(other, fun), do: to_string(other, fun) defp call_to_string_with_args(target, args, fun) do target = call_to_string(target, fun) args = args_to_string(args, fun) target <> "(" <> args <> ")" end defp args_to_string(args, fun) do {list, last} = :elixir_utils.split_last(args) if last != [] and Keyword.keyword?(last) do args = Enum.map_join(list, ", ", &to_string(&1, fun)) if list != [], do: args = args <> ", " args <> kw_list_to_string(last, fun) else Enum.map_join(args, ", ", &to_string(&1, fun)) end end defp kw_blocks_to_string(kw, fun) do Enum.reduce(@kw_keywords, " ", fn(x, acc) -> case Keyword.has_key?(kw, x) do true -> acc <> kw_block_to_string(x, Keyword.get(kw, x), fun) false -> acc end end) <> "end" end defp kw_block_to_string(key, value, fun) do block = adjust_new_lines block_to_string(value, fun), "\n " Atom.to_string(key) <> "\n " <> block <> "\n" end defp block_to_string([{:->, _, _}|_] = block, fun) do Enum.map_join(block, "\n", fn({:->, _, [left, right]}) -> left = comma_join_or_empty_paren(left, fun, false) left <> "->\n " <> adjust_new_lines block_to_string(right, fun), "\n " end) end defp block_to_string({:__block__, _, exprs}, fun) do Enum.map_join(exprs, "\n", &to_string(&1, fun)) end defp block_to_string(other, fun), do: to_string(other, fun) defp map_to_string([{:|, _, [update_map, update_args]}], fun) do to_string(update_map, fun) <> " | " <> map_to_string(update_args, fun) end defp map_to_string(list, fun) do cond do Keyword.keyword?(list) -> kw_list_to_string(list, fun) true -> map_list_to_string(list, fun) end end defp kw_list_to_string(list, fun) do Enum.map_join(list, ", ", fn {key, value} -> atom_name = case Inspect.Atom.inspect(key) do ":" <> rest -> rest other -> other end atom_name <> ": " <> to_string(value, fun) end) end defp map_list_to_string(list, fun) do Enum.map_join(list, ", ", fn {key, value} -> to_string(key, fun) <> " => " <> to_string(value, fun) end) end defp parenthise(expr, fun) do "(" <> to_string(expr, fun) <> ")" end defp op_to_string({op, _, [_, _]} = expr, fun, parent_op, side) when op in unquote(@binary_ops) do {parent_assoc, parent_prec} = binary_op_props(parent_op) {_, prec} = binary_op_props(op) cond do parent_prec < prec -> to_string(expr, fun) parent_prec > prec -> parenthise(expr, fun) true -> # parent_prec == prec, so look at associativity. if parent_assoc == side do to_string(expr, fun) else parenthise(expr, fun) end end end defp op_to_string(expr, fun, _, _), do: to_string(expr, fun) defp arrow_to_string(pairs, fun, paren \\ false) do Enum.map_join(pairs, "; ", fn({:->, _, [left, right]}) -> left = comma_join_or_empty_paren(left, fun, paren) left <> "-> " <> to_string(right, fun) end) end defp comma_join_or_empty_paren([], _fun, true), do: "() " defp comma_join_or_empty_paren([], _fun, false), do: "" defp comma_join_or_empty_paren(left, fun, _) do Enum.map_join(left, ", ", &to_string(&1, fun)) <> " " end defp adjust_new_lines(block, replacement) do for <>, into: "" do case x == ?\n do true -> replacement false -> <> end end end @doc """ Receives an AST node and expands it once. The following contents are expanded: * Macros (local or remote) * Aliases are expanded (if possible) and return atoms * Pseudo-variables (`__ENV__`, `__MODULE__` and `__DIR__`) * Module attributes reader (`@foo`) If the expression cannot be expanded, it returns the expression itself. Notice that `expand_once/2` performs the expansion just once and it is not recursive. Check `expand/2` for expansion until the node can no longer be expanded. ## Examples In the example below, we have a macro that generates a module with a function named `name_length` that returns the length of the module name. The value of this function will be calculated at compilation time and not at runtime. Consider the implementation below: defmacro defmodule_with_length(name, do: block) do length = length(Atom.to_char_list(name)) quote do defmodule unquote(name) do def name_length, do: unquote(length) unquote(block) end end end When invoked like this: defmodule_with_length My.Module do def other_function, do: ... end The compilation will fail because `My.Module` when quoted is not an atom, but a syntax tree as follow: {:__aliases__, [], [:My, :Module]} That said, we need to expand the aliases node above to an atom, so we can retrieve its length. Expanding the node is not straight-forward because we also need to expand the caller aliases. For example: alias MyHelpers, as: My defmodule_with_length My.Module do def other_function, do: ... end The final module name will be `MyHelpers.Module` and not `My.Module`. With `Macro.expand/2`, such aliases are taken into consideration. Local and remote macros are also expanded. We could rewrite our macro above to use this function as: defmacro defmodule_with_length(name, do: block) do expanded = Macro.expand(name, __CALLER__) length = length(Atom.to_char_list(expanded)) quote do defmodule unquote(name) do def name_length, do: unquote(length) unquote(block) end end end """ def expand_once(ast, env) do elem(do_expand_once(ast, env), 0) end defp do_expand_once({:__aliases__, _, _} = original, env) do case :elixir_aliases.expand(original, env.aliases, env.macro_aliases, env.lexical_tracker) do receiver when is_atom(receiver) -> :elixir_lexical.record_remote(receiver, env.lexical_tracker) {receiver, true} aliases -> aliases = :lists.map(&elem(do_expand_once(&1, env), 0), aliases) case :lists.all(&is_atom/1, aliases) do true -> receiver = :elixir_aliases.concat(aliases) :elixir_lexical.record_remote(receiver, env.lexical_tracker) {receiver, true} false -> {original, false} end end end # Expand @ calls defp do_expand_once({:@, _, [{name, _, args}]} = original, env) when is_atom(args) or args == [] do case (module = env.module) && Module.open?(module) do true -> {escape(Module.get_attribute(module, name)), true} false -> {original, false} end end # Expand pseudo-variables defp do_expand_once({:__MODULE__, _, atom}, env) when is_atom(atom), do: {env.module, true} defp do_expand_once({:__DIR__, _, atom}, env) when is_atom(atom), do: {:filename.dirname(env.file), true} defp do_expand_once({:__ENV__, _, atom}, env) when is_atom(atom), do: {{:%{}, [], Map.to_list(env)}, true} defp do_expand_once({{:., _, [{:__ENV__, _, atom}, field]}, _, []} = original, env) when is_atom(atom) and is_atom(field) do if Map.has_key?(env, field) do {Map.get(env, field), true} else {original, false} end end # Expand possible macro import invocation defp do_expand_once({atom, meta, context} = original, env) when is_atom(atom) and is_list(meta) and is_atom(context) do if :lists.member({atom, Keyword.get(meta, :counter, context)}, env.vars) do {original, false} else case do_expand_once({atom, meta, []}, env) do {_, true} = exp -> exp {_, false} -> {original, false} end end end defp do_expand_once({atom, meta, args} = original, env) when is_atom(atom) and is_list(args) and is_list(meta) do arity = length(args) if :elixir_import.special_form(atom, arity) do {original, false} else module = env.module extra = if function_exported?(module, :__info__, 1) do [{module, module.__info__(:macros)}] else [] end expand = :elixir_dispatch.expand_import(meta, {atom, length(args)}, args, env, extra, true) case expand do {:ok, receiver, quoted} -> next = :elixir_counter.next {:elixir_quote.linify_with_context_counter(0, {receiver, next}, quoted), true} {:ok, _receiver, _name, _args} -> {original, false} :error -> {original, false} end end end # Expand possible macro require invocation defp do_expand_once({{:., _, [left, right]}, meta, args} = original, env) when is_atom(right) do {receiver, _} = do_expand_once(left, env) case is_atom(receiver) do false -> {original, false} true -> expand = :elixir_dispatch.expand_require(meta, receiver, {right, length(args)}, args, env) case expand do {:ok, receiver, quoted} -> next = :elixir_counter.next {:elixir_quote.linify_with_context_counter(0, {receiver, next}, quoted), true} :error -> {original, false} end end end # Anything else is just returned defp do_expand_once(other, _env), do: {other, false} @doc """ Receives an AST node and expands it until it can no longer be expanded. This function uses `expand_once/2` under the hood. Check `expand_once/2` for more information and examples. """ def expand(tree, env) do expand_until({tree, true}, env) end defp expand_until({tree, true}, env) do expand_until(do_expand_once(tree, env), env) end defp expand_until({tree, false}, _env) do tree end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/macro/000077500000000000000000000000001254730255300210265ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/macro/env.ex000066400000000000000000000110221254730255300221500ustar00rootroot00000000000000defmodule Macro.Env do @moduledoc """ A struct that holds compile time environment information. The current environment can be accessed at any time as `__ENV__`. Inside macros, the caller environment can be accessed as `__CALLER__`. An instance of `Macro.Env` must not be modified by hand. If you need to create a custom environment to pass to `Code.eval_quoted/3`, use the following trick: def make_custom_env do import SomeModule, only: [some_function: 2] alias A.B.C __ENV__ end You may then call `make_custom_env()` to get a struct with the desired imports and aliases included. It contains the following fields: * `module` - the current module name * `file` - the current file name as a binary * `line` - the current line as an integer * `function` - a tuple as `{atom, integer`}, where the first element is the function name and the seconds its arity; returns `nil` if not inside a function * `context` - the context of the environment; it can be `nil` (default context), inside a guard or inside an assign * `aliases` - a list of two item tuples, where the first item is the aliased name and the second the actual name * `requires` - the list of required modules * `functions` - a list of functions imported from each module * `macros` - a list of macros imported from each module * `macro_aliases` - a list of aliases defined inside the current macro * `context_modules` - a list of modules defined in the current context * `vars` - a list keeping all defined variables as `{var, context}` * `export_vars` - a list keeping all variables to be exported in a construct (may be `nil`) * `lexical_tracker` - PID of the lexical tracker which is responsible to keep user info * `local` - the module to expand local functions to """ @type name_arity :: {atom, arity} @type file :: binary @type line :: non_neg_integer @type aliases :: [{module, module}] @type macro_aliases :: [{module, {integer, module}}] @type context :: :match | :guard | nil @type requires :: [module] @type functions :: [{module, [name_arity]}] @type macros :: [{module, [name_arity]}] @type context_modules :: [module] @type vars :: [{atom, atom | non_neg_integer}] @type export_vars :: vars | nil @type lexical_tracker :: pid @type local :: atom | nil @type t :: %{__struct__: __MODULE__, module: atom, file: file, line: line, function: name_arity | nil, context: context, requires: requires, aliases: aliases, functions: functions, macros: macros, macro_aliases: aliases, context_modules: context_modules, vars: vars, export_vars: export_vars, lexical_tracker: lexical_tracker, local: local} def __struct__ do %{__struct__: __MODULE__, module: nil, file: "nofile", line: 0, function: nil, context: nil, requires: [], aliases: [], functions: [], macros: [], macro_aliases: [], context_modules: [], vars: [], export_vars: nil, lexical_tracker: nil} end @doc """ Returns a keyword list containing the file and line information as keys. """ @spec location(t) :: Keyword.t def location(env) def location(%{__struct__: Macro.Env, file: file, line: line}) do [file: file, line: line] end @doc """ Returns whether the compilation environment is currently inside a guard. """ @spec in_guard?(t) :: boolean def in_guard?(env) def in_guard?(%{__struct__: Macro.Env, context: context}), do: context == :guard @doc """ Returns whether the compilation environment is currently inside a match clause. """ @spec in_match?(t) :: boolean def in_match?(env) def in_match?(%{__struct__: Macro.Env, context: context}), do: context == :match @doc """ Returns the environment stacktrace. """ @spec stacktrace(t) :: list def stacktrace(%{__struct__: Macro.Env} = env) do cond do is_nil(env.module) -> [{:elixir_compiler, :__FILE__, 1, relative_location(env)}] is_nil(env.function) -> [{env.module, :__MODULE__, 0, relative_location(env)}] true -> {name, arity} = env.function [{env.module, name, arity, relative_location(env)}] end end defp relative_location(env) do [file: Path.relative_to_cwd(env.file), line: env.line] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/map.ex000066400000000000000000000035071254730255300210450ustar00rootroot00000000000000defmodule Map do @moduledoc """ A Dict implementation that works on maps. Maps are key-value stores where keys are compared using the match operator (`===`). Maps can be created with the `%{}` special form defined in the `Kernel.SpecialForms` module. For more information about the functions in this module and their APIs, please consult the `Dict` module. """ use Dict defdelegate [keys(map), values(map), size(map), merge(map1, map2), to_list(map)], to: :maps @compile {:inline, fetch: 2, put: 3, delete: 2, has_key?: 2} @doc """ Returns a new empty map. """ def new, do: %{} def has_key?(map, key), do: :maps.is_key(key, map) def fetch(map, key), do: :maps.find(key, map) def put(map, key, val) do :maps.put(key, val, map) end def delete(map, key), do: :maps.remove(key, map) def merge(map1, map2, callback) do :maps.fold fn k, v2, acc -> update(acc, k, v2, fn(v1) -> callback.(k, v1, v2) end) end, map1, map2 end def get_and_update(map, key, fun) do current_value = case :maps.find(key, map) do {:ok, value} -> value :error -> nil end {get, update} = fun.(current_value) {get, :maps.put(key, update, map)} end @doc """ Converts a struct to map. It accepts the struct module or a struct itself and simply removes the `__struct__` field from the struct. ## Example defmodule User do defstruct [:name] end Map.from_struct(User) #=> %{name: nil} Map.from_struct(%User{name: "john"}) #=> %{name: "john"} """ def from_struct(struct) when is_atom(struct) do :maps.remove(:__struct__, struct.__struct__) end def from_struct(%{__struct__: _} = struct) do :maps.remove(:__struct__, struct) end def equal?(map1, map2) def equal?(%{} = map1, %{} = map2), do: map1 === map2 end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/map_set.ex000066400000000000000000000054721254730255300217230ustar00rootroot00000000000000defmodule MapSet do @moduledoc """ A set store. The `MapSet` is represented internally as a struct, therefore `%MapSet{}` can be used whenever there is a need to match on any `MapSet`. Note though the struct fields are private and must not be accessed directly. Instead, use the functions on this or in the `Set` module. The `MapSet` is implemented using `Map` data type. For more information about the functions and their APIs, please consult the `Set` module. """ @behaviour Set defstruct map: %{} def new(), do: %MapSet{} def delete(%MapSet{map: map} = set, term) do %{set | map: Map.delete(map, term)} end def difference(%MapSet{} = set1, %MapSet{} = set2) do reduce(set2, {:cont, set1}, fn value, acc -> {:cont, delete(acc, value)} end) |> elem(1) end def disjoint?(%MapSet{} = set1, %MapSet{} = set2) do if size(set1) > size(set2), do: {set1, set2} = {set2, set1} reduce(set1, {:cont, true}, fn value, _ -> if member?(set2, value) do {:halt, false} else {:cont, true} end end) |> elem(1) end def equal?(%MapSet{map: map1}, %MapSet{map: map2}) do Map.equal?(map1, map2) end def intersection(%MapSet{} = set1, %MapSet{} = set2) do if size(set1) > size(set2), do: {set1, set2} = {set2, set1} reduce(set1, {:cont, new}, fn value, acc -> if member?(set2, value) do {:cont, put(acc, value)} else {:cont, acc} end end) |> elem(1) end def member?(%MapSet{map: map}, value) do Map.has_key?(map, value) end def put(%MapSet{map: map} = set, value) do %{set | map: Map.put(map, value, nil)} end def size(%MapSet{map: map}) do map_size(map) end def subset?(%MapSet{} = set1, %MapSet{} = set2) do if size(set1) <= size(set2) do reduce(set1, {:cont, true}, fn value, _ -> if member?(set2, value), do: {:cont, true}, else: {:halt, false} end) |> elem(1) else false end end @doc false def reduce(%MapSet{} = set, acc, fun) do Enumerable.List.reduce(to_list(set), acc, fun) end def to_list(%MapSet{map: map}) do Map.keys(map) end def union(%MapSet{map: map1}, %MapSet{map: map2}) do %MapSet{map: Map.merge(map1, map2)} end defimpl Enumerable do def reduce(set, acc, fun), do: MapSet.reduce(set, acc, fun) def member?(set, val), do: {:ok, MapSet.member?(set, val)} def count(set), do: {:ok, MapSet.size(set)} end defimpl Collectable do def into(original) do {original, fn set, {:cont, x} -> MapSet.put(set, x) set, :done -> set _, :halt -> :ok end} end end defimpl Inspect do import Inspect.Algebra def inspect(set, opts) do concat ["#MapSet<", Inspect.List.inspect(MapSet.to_list(set), opts), ">"] end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/module.ex000066400000000000000000000735201254730255300215570ustar00rootroot00000000000000defmodule Module do @moduledoc ~S''' This module provides many functions to deal with modules during compilation time. It allows a developer to dynamically attach documentation, add, delete and register attributes and so forth. After a module is compiled, using many of the functions in this module will raise errors, since it is out of their scope to inspect runtime data. Most of the runtime data can be inspected via the `__info__(attr)` function attached to each compiled module. ## Module attributes Each module can be decorated with one or more attributes. The following ones are currently defined by Elixir: * `@after_compile` A hook that will be invoked right after the current module is compiled. Accepts a module or a tuple `{, }`. The function must take two arguments: the module environment and its bytecode. When just a module is provided, the function is assumed to be `__after_compile__/2`. ### Example defmodule M do @after_compile __MODULE__ def __after_compile__(env, _bytecode) do IO.inspect env end end * `@before_compile` A hook that will be invoked before the module is compiled. Accepts a module or a tuple `{, }`. The function/macro must take one argument: the module environment. If it's a macro, its returned value will be injected at the end of the module definition before the compilation starts. When just a module is provided, the function/macro is assumed to be `__before_compile__/1`. Note: unlike `@after_compile`, the callback function/macro must be placed in a separate module (because when the callback is invoked, the current module does not yet exist). ### Example defmodule A do defmacro __before_compile__(_env) do quote do def hello, do: "world" end end end defmodule B do @before_compile A end * `@behaviour` (notice the British spelling) Specifies an OTP or user-defined behaviour. ### Example defmodule M do @behaviour gen_event # ... end * `@compile` Defines options for module compilation that are passed to the Erlang compiler. Accepts an atom, a tuple, or a list of atoms and tuples. See http://www.erlang.org/doc/man/compile.html for the list of supported options. Several uses of `@compile` will accumulate instead of overriding previous ones. ### Example defmodule M do @compile {:inline, myfun: 1} def myfun(arg) do to_string(arg) end end * `@doc` Provides documentation for the function or macro that follows the attribute. Accepts a string (often a heredoc) or `false` where `@doc false` will make the function/macro invisible to the documentation extraction tools like ExDoc. Can be invoked more than once. ### Example defmodule M do @doc "Hello world" def hello do "world" end @doc """ Sum. """ def sum(a, b) do a + b end end * `@file` Changes the filename used in stacktraces for the function or macro that follows the attribute. Accepts a string. Can be used more than once. ### Example defmodule M do @doc "Hello world" @file "hello.ex" def hello do "world" end end * `@moduledoc` Provides documentation for the current module. Accepts a string (which is often a heredoc) or `false` where `@moduledoc false` will make the module invisible to the documentation extraction tools like ExDoc. ### Example defmodule M do @moduledoc """ A very useful module """ end * `@on_definition` A hook that will be invoked when each function or macro in the current module is defined. Useful when annotating functions. Accepts a module or a tuple `{, }`. The function must take 6 arguments: - the module environment - kind: `:def`, `:defp`, `:defmacro`, or `:defmacrop` - function/macro name - list of quoted arguments - list of quoted guards - quoted function body Note the hook receives the quoted arguments and it is invoked before the function is stored in the module. So `Module.defines?/2` will return `false` for the first clause of every function. If the function/macro being defined has multiple clauses, the hook will be called for each clause. Unlike other hooks, `@on_definition` will only invoke functions and never macros. This is because the hook is invoked inside the context of the function (and nested function definitions are not allowed in Elixir). When just a module is provided, the function is assumed to be `__on_definition__/6`. ### Example defmodule H do def on_def(_env, kind, name, args, guards, body) do IO.puts "Defining #{kind} named #{name} with args:" IO.inspect args IO.puts "and guards" IO.inspect guards IO.puts "and body" IO.puts Macro.to_string(body) end end defmodule M do @on_definition {H, :on_def} def hello(arg) when is_binary(arg) or is_list(arg) do "Hello" <> to_string(arg) end def hello(_) do :ok end end * `@on_load` A hook that will be invoked whenever the module is loaded. Accepts a function atom of a function in the current module. The function must have arity 0 (no arguments) and has to return `:ok`, otherwise the loading of the module will be aborted. ### Example defmodule M do @on_load :load_check def load_check do if some_condition() do :ok else nil end end def some_condition do false end end * `@vsn` Specify the module version. Accepts any valid Elixir value. ### Example defmodule M do @vsn "1.0" end * `@external_resource` Specifies an external resource to the current module. Many times a module embeds information from an external file. This attribute allows the module to annotate which external resources have been used. Tools like Mix may use this information to ensure the module is recompiled in case any of the external resources change. * `@dialyzer` Defines warnings to request or suppress when using a version of `dialyzer` that supports module attributes. Accepts an atom, a tuple, or a list of atoms and tuples. See http://www.erlang.org/doc/man/dialyzer.html for the list of supported warnings. Several uses of `@dialyzer` will accumulate instead of overriding previous ones. ### Example defmodule M do @dialyzer {:nowarn_function, myfun: 1} def myfun(arg) do M.not_a_function(arg) end end The following attributes are part of typespecs and are also reserved by Elixir (see `Kernel.Typespec` for more information about typespecs): * `@type` - defines a type to be used in `@spec` * `@typep` - defines a private type to be used in `@spec` * `@opaque` - defines an opaque type to be used in `@spec` * `@spec` - provides a specification for a function * `@callback` - provides a specification for the behaviour callback In addition to the built-in attributes outlined above, custom attributes may also be added. A custom attribute is any valid identifier prefixed with an `@` and followed by a valid Elixir value: defmodule M do @custom_attr [some: "stuff"] end For more advanced options available when defining custom attributes, see `register_attribute/3`. ## Runtime information about a module It is possible to query a module at runtime to find out which functions and macros it defines, extract its docstrings, etc. See `__info__/1`. ''' @doc """ Provides runtime information about functions and macros defined by the module, enables docstring extraction, etc. Each module gets an `__info__/1` function when it's compiled. The function takes one of the following atoms: * `:functions` - keyword list of public functions along with their arities * `:macros` - keyword list of public macros along with their arities * `:module` - module name (`Module == Module.__info__(:module)`) In addition to the above, you may also pass to `__info__/1` any atom supported by Erlang's `module_info` function which also gets defined for each compiled module. See http://erlang.org/doc/reference_manual/modules.html#id75777 for more information. """ def __info__(kind) @doc """ Checks if a module is open, i.e. it is currently being defined and its attributes and functions can be modified. """ def open?(module) do :elixir_module.is_open(module) end @doc """ Evaluates the quoted contents in the given module's context. A list of environment options can also be given as argument. See `Code.eval_string/3` for more information. Raises an error if the module was already compiled. ## Examples defmodule Foo do contents = quote do: (def sum(a, b), do: a + b) Module.eval_quoted __MODULE__, contents end Foo.sum(1, 2) #=> 3 For convenience, you can pass `__ENV__` as an argument and all options will be automatically extracted from the environment: defmodule Foo do contents = quote do: (def sum(a, b), do: a + b) Module.eval_quoted __MODULE__, contents, [], __ENV__ end Foo.sum(1, 2) #=> 3 """ def eval_quoted(module, quoted, binding \\ [], opts \\ []) def eval_quoted(%Macro.Env{} = env, quoted, binding, opts) do eval_quoted(env.module, quoted, binding, Keyword.merge(Map.to_list(env), opts)) end def eval_quoted(module, quoted, binding, %Macro.Env{} = env) do eval_quoted(module, quoted, binding, Map.to_list(env)) end def eval_quoted(module, quoted, binding, opts) do assert_not_compiled!(:eval_quoted, module) :elixir_def.reset_last(module) {value, binding, _env, _scope} = :elixir.eval_quoted quoted, binding, Keyword.put(opts, :module, module) {value, binding} end @doc """ Creates a module with the given name and defined by the given quoted expressions. The line where the module is defined and its file **must** be passed as options. ## Examples contents = quote do def world, do: true end Module.create(Hello, contents, Macro.Env.location(__ENV__)) Hello.world #=> true ## Differences from `defmodule` `Module.create` works similarly to `defmodule` and return the same results. While one could also use `defmodule` to define modules dynamically, this function is preferred when the module body is given by a quoted expression. Another important distinction is that `Module.create` allows you to control the environment variables used when defining the module, while `defmodule` automatically shares the same environment. """ def create(module, quoted, opts) def create(module, quoted, %Macro.Env{} = env) do create(module, quoted, Map.to_list(env)) end def create(module, quoted, opts) when is_atom(module) and is_list(opts) do unless Keyword.has_key?(opts, :file) do raise ArgumentError, "expected :file to be given as option" end :elixir_module.compile(module, quoted, [], :elixir.env_for_eval(opts)) end @doc """ Concatenates a list of aliases and returns a new alias. ## Examples iex> Module.concat([Foo, Bar]) Foo.Bar iex> Module.concat([Foo, "Bar"]) Foo.Bar """ @spec concat([binary | atom]) :: atom def concat(list) when is_list(list) do :elixir_aliases.concat(list) end @doc """ Concatenates two aliases and returns a new alias. ## Examples iex> Module.concat(Foo, Bar) Foo.Bar iex> Module.concat(Foo, "Bar") Foo.Bar """ @spec concat(binary | atom, binary | atom) :: atom def concat(left, right) do :elixir_aliases.concat([left, right]) end @doc """ Concatenates a list of aliases and returns a new alias only if the alias was already referenced. If the alias was not referenced yet, fails with `ArgumentError`. It handles char lists, binaries and atoms. ## Examples iex> Module.safe_concat([Unknown, Module]) ** (ArgumentError) argument error iex> Module.safe_concat([List, Chars]) List.Chars """ @spec safe_concat([binary | atom]) :: atom | no_return def safe_concat(list) when is_list(list) do :elixir_aliases.safe_concat(list) end @doc """ Concatenates two aliases and returns a new alias only if the alias was already referenced. If the alias was not referenced yet, fails with `ArgumentError`. It handles char lists, binaries and atoms. ## Examples iex> Module.safe_concat(Unknown, Module) ** (ArgumentError) argument error iex> Module.safe_concat(List, Chars) List.Chars """ @spec safe_concat(binary | atom, binary | atom) :: atom | no_return def safe_concat(left, right) do :elixir_aliases.safe_concat([left, right]) end @doc """ Attaches documentation to a given function or type. It expects the module the function/type belongs to, the line (a non negative integer), the kind (`def` or `defmacro`), a tuple representing the function and its arity, the function signature (the signature should be omitted for types) and the documentation, which should be either a binary or a boolean. ## Examples defmodule MyModule do Module.add_doc(__MODULE__, __ENV__.line + 1, :def, {:version, 0}, [], "Manually added docs") def version, do: 1 end """ def add_doc(module, line, kind, tuple, signature \\ [], doc) def add_doc(_module, _line, kind, _tuple, _signature, doc) when kind in [:defp, :defmacrop, :typep] do if doc, do: {:error, :private_doc}, else: :ok end def add_doc(module, line, kind, tuple, signature, doc) when kind in [:def, :defmacro, :type, :opaque] and (is_binary(doc) or is_boolean(doc) or doc == nil) do assert_not_compiled!(:add_doc, module) table = data_table_for(module) signature = simplify_signature(signature) case :ets.lookup(table, {:doc, tuple}) do [] -> :ets.insert(table, {{:doc, tuple}, line, kind, signature, doc}) :ok [{doc_tuple, line, _old_kind, old_sign, old_doc}] -> :ets.insert(table, { doc_tuple, line, kind, merge_signatures(old_sign, signature, 1), if(is_nil(doc), do: old_doc, else: doc) }) :ok end end # Simplify signatures to be stored in docs defp simplify_signature(signature) do {signature, acc} = :lists.mapfoldl(&simplify_signature/2, [], signature) {signature, _} = :lists.mapfoldl(&expand_signature/2, {acc, acc}, signature) signature end defp simplify_signature({:\\, _, [left, right ]}, acc) do {left, acc} = simplify_signature(left, acc) {{:\\, [], [left, right]}, acc} end defp simplify_signature({:=, _, [_, right]}, acc) do simplify_signature(right, acc) end defp simplify_signature({var, _, atom}, acc) when is_atom(atom) do case Atom.to_string(var) do "_" <> rest -> {{String.to_atom(rest), [], Elixir}, acc} _ -> {{var, [], nil}, acc} end end defp simplify_signature({:%, _, [left, _]}, acc) when is_atom(left) do struct_name = String.to_atom(camelcase_to_underscore(List.last(split(left)))) autogenerated(acc, struct_name) end defp simplify_signature({:%{}, _, _}, acc) do autogenerated(acc, :map) end defp simplify_signature(other, acc) when is_integer(other), do: autogenerated(acc, :int) defp simplify_signature(other, acc) when is_boolean(other), do: autogenerated(acc, :bool) defp simplify_signature(other, acc) when is_atom(other), do: autogenerated(acc, :atom) defp simplify_signature(other, acc) when is_list(other), do: autogenerated(acc, :list) defp simplify_signature(other, acc) when is_float(other), do: autogenerated(acc, :float) defp simplify_signature(other, acc) when is_binary(other), do: autogenerated(acc, :binary) defp simplify_signature(_, acc), do: autogenerated(acc, :arg) defp autogenerated(acc, key) do {key, [key|acc]} end defp expand_signature(key, {all_keys, acc}) when is_atom(key) do case previous_values(key, all_keys, acc) do {i, acc} -> {{:"#{key}#{i}", [], Elixir}, {all_keys, acc}} :none -> {{key, [], Elixir}, {all_keys, acc}} end end defp expand_signature(term, {_, _} = acc) do {term, acc} end defp previous_values(key, all_keys, acc) do total_occurrences = occurrences(key, all_keys) if total_occurrences == 1 do :none else index = total_occurrences - occurrences(key, acc) + 1 {index, :lists.delete(key, acc)} end end defp occurrences(key, list) do length(:lists.filter(fn(el) -> el == key end, list)) end defp camelcase_to_underscore(<>) when c >= ?A and c <= ?Z, do: do_camelcase_to_underscore(rest, <>) defp do_camelcase_to_underscore(<>, acc) when c >= ?A and c <= ?Z, do: do_camelcase_to_underscore(rest, <>) defp do_camelcase_to_underscore(<>, acc), do: do_camelcase_to_underscore(rest, <>) defp do_camelcase_to_underscore(<<>>, acc), do: acc # Merge defp merge_signatures([h1|t1], [h2|t2], i) do [merge_signature(h1, h2, i)|merge_signatures(t1, t2, i + 1)] end defp merge_signatures([], [], _) do [] end defp merge_signature({:\\, line, [left, right]}, newer, i) do {:\\, line, [merge_signature(left, newer, i), right]} end defp merge_signature(older, {:\\, _, [left, _]}, i) do merge_signature(older, left, i) end # The older signature, when given, always have higher precedence defp merge_signature({_, _, nil} = older, _newer, _), do: older defp merge_signature(_older, {_, _, nil} = newer, _), do: newer # Both are a guess, so check if they are the same guess defp merge_signature({var, _, _} = older, {var, _, _}, _), do: older # Otherwise, returns a generic guess defp merge_signature({_, line, _}, _newer, i), do: {:"arg#{i}", line, Elixir} @doc """ Checks if the module defines the given function or macro. Use `defines?/3` to assert for a specific type. ## Examples defmodule Example do Module.defines? __MODULE__, {:version, 0} #=> false def version, do: 1 Module.defines? __MODULE__, {:version, 0} #=> true end """ def defines?(module, tuple) when is_tuple(tuple) do assert_not_compiled!(:defines?, module) table = defs_table_for(module) :ets.lookup(table, tuple) != [] end @doc """ Checks if the module defines a function or macro of the given `kind`. `kind` can be any of `:def`, `:defp`, `:defmacro` or `:defmacrop`. ## Examples defmodule Example do Module.defines? __MODULE__, {:version, 0}, :defp #=> false def version, do: 1 Module.defines? __MODULE__, {:version, 0}, :defp #=> false end """ def defines?(module, tuple, kind) do assert_not_compiled!(:defines?, module) table = defs_table_for(module) case :ets.lookup(table, tuple) do [{_, ^kind, _, _, _, _, _}] -> true _ -> false end end @doc """ Returns all functions defined in `module`. ## Examples defmodule Example do def version, do: 1 Module.definitions_in __MODULE__ #=> [{:version, 0}] end """ def definitions_in(module) do assert_not_compiled!(:definitions_in, module) table = defs_table_for(module) :lists.concat :ets.match(table, {:'$1', :_, :_, :_, :_, :_, :_}) end @doc """ Returns all functions defined in `module`, according to its kind. ## Examples defmodule Example do def version, do: 1 Module.definitions_in __MODULE__, :def #=> [{:version, 0}] Module.definitions_in __MODULE__, :defp #=> [] end """ def definitions_in(module, kind) do assert_not_compiled!(:definitions_in, module) table = defs_table_for(module) :lists.concat :ets.match(table, {:'$1', kind, :_, :_, :_, :_, :_}) end @doc """ Makes the given functions in `module` overridable. An overridable function is lazily defined, allowing a developer to customize it. See `Kernel.defoverridable/1` for more information and documentation. """ def make_overridable(module, tuples) do assert_not_compiled!(:make_overridable, module) :lists.foreach(fn tuple -> case :elixir_def.lookup_definition(module, tuple) do false -> {name, arity} = tuple raise "cannot make function #{name}/#{arity} overridable because it was not defined" clause -> :elixir_def.delete_definition(module, tuple) neighbours = if :elixir_compiler.get_opt(:internal) do [] else Module.LocalsTracker.yank(module, tuple) end old = :elixir_def_overridable.overridable(module) merged = :orddict.update(tuple, fn({count, _, _, _}) -> {count + 1, clause, neighbours, false} end, {1, clause, neighbours, false}, old) :elixir_def_overridable.overridable(module, merged) end end, tuples) end @doc """ Returns `true` if `tuple` in `module` is marked as overridable. """ def overridable?(module, tuple) do !!List.keyfind(:elixir_def_overridable.overridable(module), tuple, 0) end @doc """ Puts an Erlang attribute to the given module with the given key and value. The semantics of putting the attribute depends if the attribute was registered or not via `register_attribute/3`. ## Examples defmodule MyModule do Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10 end """ def put_attribute(module, key, value) when is_atom(key) do assert_not_compiled!(:put_attribute, module) table = data_table_for(module) value = normalize_attribute(key, value) acc = :ets.lookup_element(table, {:elixir, :acc_attributes}, 2) new = if :lists.member(key, acc) do case :ets.lookup(table, key) do [{^key, old}] -> [value|old] [] -> [value] end else value end :ets.insert(table, {key, new}) end @doc """ Gets the given attribute from a module. If the attribute was marked with `accumulate` with `Module.register_attribute/3`, a list is always returned. The `@` macro compiles to a call to this function. For example, the following code: @foo Expands close to: Module.get_attribute(__MODULE__, :foo) ## Examples defmodule Foo do Module.put_attribute __MODULE__, :value, 1 Module.get_attribute __MODULE__, :value #=> 1 Module.register_attribute __MODULE__, :value, accumulate: true Module.put_attribute __MODULE__, :value, 1 Module.get_attribute __MODULE__, :value #=> [1] end """ @spec get_attribute(atom, atom) :: term def get_attribute(module, key) do get_attribute(module, key, nil) end @doc """ Deletes all attributes that match the given key. ## Examples defmodule MyModule do Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10 Module.delete_attribute __MODULE__, :custom_threshold_for_lib end """ @spec delete_attribute(atom, atom) :: :ok def delete_attribute(module, key) when is_atom(key) do assert_not_compiled!(:delete_attribute, module) table = data_table_for(module) :ets.delete(table, key) :ok end @doc """ Registers an attribute. By registering an attribute, a developer is able to customize how Elixir will store and accumulate the attribute values. ## Options When registering an attribute, two options can be given: * `:accumulate` - several calls to the same attribute will accumulate instead of override the previous one. New attributes are always added to the top of the accumulated list. * `:persist` - the attribute will be persisted in the Erlang Abstract Format. Useful when interfacing with Erlang libraries. By default, both options are `false`. ## Examples defmodule MyModule do Module.register_attribute __MODULE__, :custom_threshold_for_lib, accumulate: true, persist: false @custom_threshold_for_lib 10 @custom_threshold_for_lib 20 @custom_threshold_for_lib #=> [20, 10] end """ def register_attribute(module, new, opts) when is_atom(new) do assert_not_compiled!(:register_attribute, module) table = data_table_for(module) if Keyword.get(opts, :persist) do old = :ets.lookup_element(table, {:elixir, :persisted_attributes}, 2) :ets.insert(table, {{:elixir, :persisted_attributes}, [new|old]}) end if Keyword.get(opts, :accumulate) do old = :ets.lookup_element(table, {:elixir, :acc_attributes}, 2) :ets.insert(table, {{:elixir, :acc_attributes}, [new|old]}) end end @doc """ Splits the given module name into binary parts. ## Examples Module.split Very.Long.Module.Name.And.Even.Longer #=> ["Very", "Long", "Module", "Name", "And", "Even", "Longer"] """ def split(module) when is_atom(module) do split(String.Chars.to_string(module)) end def split("Elixir." <> name) do String.split(name, ".") end @doc false # Used internally to compile documentation. This function # is private and must be used only internally. def compile_doc(env, kind, name, args, _guards, _body) do module = env.module line = env.line arity = length(args) pair = {name, arity} doc = get_attribute(module, :doc) # Arguments are not expanded for the docs, but we make an exception for # module attributes and for structs (aliases to be precise). args = Macro.prewalk args, fn {:@, _, _} = attr -> Macro.expand_once(attr, env) {:%, meta, [aliases, fields]} -> {:%, meta, [Macro.expand_once(aliases, env), fields]} x -> x end case add_doc(module, line, kind, pair, args, doc) do :ok -> :ok {:error, :private_doc} -> :elixir_errors.warn line, env.file, "function #{name}/#{arity} is private, " <> "@doc's are always discarded for private functions" end delete_attribute(module, :doc) end @doc false # Used internally to compile types. This function # is private and must be used only internally. def store_typespec(module, key, value) when is_atom(key) do assert_not_compiled!(:put_attribute, module) table = data_table_for(module) new = case :ets.lookup(table, key) do [{^key, old}] -> [value|old] [] -> [value] end :ets.insert(table, {key, new}) end @doc false def get_attribute(module, key, warn) when is_atom(key) and (is_list(warn) or is_nil(warn)) do assert_not_compiled!(:get_attribute, module) table = data_table_for(module) case :ets.lookup(table, key) do [{^key, val}] -> val [] -> acc = :ets.lookup_element(table, {:elixir, :acc_attributes}, 2) cond do :lists.member(key, acc) -> [] is_list(warn) -> :elixir_errors.warn warn_info(warn), "undefined module attribute @#{key}, " <> "please remove access to @#{key} or explicitly set it before access" nil true -> nil end end end defp warn_info([entry|_]) do opts = elem(entry, tuple_size(entry) - 1) Exception.format_file_line(Keyword.get(opts, :file), Keyword.get(opts, :line)) <> " " end defp warn_info([]) do "" end ## Helpers defp normalize_attribute(:on_load, atom) when is_atom(atom) do {atom, 0} end defp normalize_attribute(:behaviour, atom) when is_atom(atom) do # Attempt to compile behaviour but ignore failure (will warn later) _ = Code.ensure_compiled(atom) atom end defp normalize_attribute(:file, file) when is_binary(file) do file end defp normalize_attribute(:before_compile, atom) when is_atom(atom), do: {atom, :__before_compile__} defp normalize_attribute(:after_compile, atom) when is_atom(atom), do: {atom, :__after_compile__} defp normalize_attribute(:on_definition, atom) when is_atom(atom), do: {atom, :__on_definition__} defp normalize_attribute(key, _value) when key in [:type, :typep, :export_type, :opaque, :callback] do raise ArgumentError, "attributes type, typep, export_type, opaque and callback " <> "must be set via Kernel.Typespec" end defp normalize_attribute(_key, value) do value end defp data_table_for(module) do :elixir_module.data_table(module) end defp defs_table_for(module) do :elixir_module.defs_table(module) end defp assert_not_compiled!(fun, module) do open?(module) || raise ArgumentError, "could not call #{fun} on module #{inspect module} because it was already compiled" end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/module/000077500000000000000000000000001254730255300212125ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/module/locals_tracker.ex000066400000000000000000000233051254730255300245430ustar00rootroot00000000000000# This is a module Elixir responsible for tracking # calls in order to extract Elixir modules' behaviour # during compilation time. # # ## Implementation # # The implementation uses the digraph module to track # all dependencies. The graph starts with one main vertice: # # * `:local` - points to local functions # # We also have can the following vertices: # # * `Module` - a module that was invoked via an import # * `{name, arity}` - a local function/arity pair # * `{:import, name, arity}` - an invoked function/arity import # # Each of those vertices can associate to other vertices # as described below: # # * `Module` # * in neighbours: `{:import, name, arity}` # # * `{name, arity}` # * in neighbours: `:local`, `{name, arity}` # * out neighbours: `{:import, name, arity}` # # * `{:import, name, arity}` # * in neighbours: `{name, arity}` # * out neighbours: `Module` # # Note that since this is required for bootstrap, we can't use # any of the `GenServer.Behaviour` conveniences. defmodule Module.LocalsTracker do @moduledoc false @timeout 30_000 @behaviour :gen_server @type ref :: pid | module @type name :: atom @type name_arity :: {name, arity} @type local :: {name, arity} @type import :: {:import, name, arity} # Public API @doc """ Returns all imported modules that had the given `{name, arity}` invoked. """ @spec imports_with_dispatch(ref, name_arity) :: [module] def imports_with_dispatch(ref, {name, arity}) do d = :gen_server.call(to_pid(ref), :digraph, @timeout) :digraph.out_neighbours(d, {:import, name, arity}) end @doc """ Returns all locals that are reachable. By default, all public functions are reachable. A private function is only reachable if it has a public function that it invokes directly. """ @spec reachable(ref) :: [local] def reachable(ref) do reachable_from(:gen_server.call(to_pid(ref), :digraph, @timeout), :local) end defp reachable_from(d, starting) do :sets.to_list(reduce_reachable(d, starting, :sets.new)) end defp reduce_reachable(d, vertex, vertices) do neighbours = :digraph.out_neighbours(d, vertex) neighbours = (for {_, _} = t <- neighbours, do: t) |> :sets.from_list remaining = :sets.subtract(neighbours, vertices) vertices = :sets.union(neighbours, vertices) :sets.fold(&reduce_reachable(d, &1, &2), vertices, remaining) end defp to_pid(pid) when is_pid(pid), do: pid defp to_pid(mod) when is_atom(mod) do table = :elixir_module.data_table(mod) [{_, val}] = :ets.lookup(table, {:elixir, :locals_tracker}) val end # Internal API # Starts the tracker and returns its pid. @doc false def start_link do :gen_server.start_link(__MODULE__, [], []) end # Adds a definition into the tracker. A public # definition is connected with the :local node # while a private one is left unreachable until # a call is made to. @doc false def add_definition(pid, kind, tuple) when kind in [:def, :defp, :defmacro, :defmacrop] do :gen_server.cast(pid, {:add_definition, kind, tuple}) end # Adds and tracks defaults for a definition into the tracker. @doc false def add_defaults(pid, kind, tuple, defaults) when kind in [:def, :defp, :defmacro, :defmacrop] do :gen_server.cast(pid, {:add_defaults, kind, tuple, defaults}) end # Adds a local dispatch to the given target. def add_local(pid, to) when is_tuple(to) do :gen_server.cast(pid, {:add_local, :local, to}) end # Adds a local dispatch from-to the given target. @doc false def add_local(pid, from, to) when is_tuple(from) and is_tuple(to) do :gen_server.cast(pid, {:add_local, from, to}) end # Adds a import dispatch to the given target. @doc false def add_import(pid, function, module, target) when is_atom(module) and is_tuple(target) do :gen_server.cast(pid, {:add_import, function, module, target}) end # Yanks a local node. Returns its in and out vertices in a tuple. @doc false def yank(pid, local) do :gen_server.call(to_pid(pid), {:yank, local}, @timeout) end # Reattach a previously yanked node @doc false def reattach(pid, kind, tuple, neighbours) do :gen_server.cast(to_pid(pid), {:reattach, kind, tuple, neighbours}) end # Collecting all conflicting imports with the given functions @doc false def collect_imports_conflicts(pid, all_defined) do d = :gen_server.call(pid, :digraph, @timeout) for {name, arity} <- all_defined, :digraph.in_neighbours(d, {:import, name, arity}) != [], n = :digraph.out_neighbours(d, {:import, name, arity}), n != [] do {n, name, arity} end end # Collect all unused definitions based on the private # given also accounting the expected amount of default # clauses a private function have. @doc false def collect_unused_locals(ref, private) do d = :gen_server.call(to_pid(ref), :digraph, @timeout) {unreachable(d, private), collect_warnings(d, private)} end defp unreachable(d, private) do unreachable = for {tuple, _, _} <- private, do: tuple private = for {tuple, :defp, _} <- private do neighbours = :digraph.in_neighbours(d, tuple) neighbours = for {_, _} = t <- neighbours, do: t {tuple, :sets.from_list(neighbours)} end reduce_unreachable(private, [], :sets.from_list(unreachable)) end defp reduce_unreachable([{vertex, callers}|t], acc, unreachable) do if :sets.is_subset(callers, unreachable) do reduce_unreachable(t, [{vertex, callers}|acc], unreachable) else reduce_unreachable(acc ++ t, [], :sets.del_element(vertex, unreachable)) end end defp reduce_unreachable([], _acc, unreachable) do :sets.to_list(unreachable) end defp collect_warnings(d, private) do reachable = reachable_from(d, :local) :lists.foldl(&collect_warnings(&1, &2, reachable), [], private) end defp collect_warnings({tuple, kind, 0}, acc, reachable) do if :lists.member(tuple, reachable) do acc else [{:unused_def, tuple, kind}|acc] end end defp collect_warnings({tuple, kind, default}, acc, reachable) when default > 0 do {name, arity} = tuple min = arity - default max = arity invoked = for {n, a} <- reachable, n == name, a in min..max, do: a if invoked == [] do [{:unused_def, tuple, kind}|acc] else case :lists.min(invoked) - min do 0 -> acc ^default -> [{:unused_args, tuple}|acc] unused_args -> [{:unused_args, tuple, unused_args}|acc] end end end @doc false def cache_env(pid, env) do :gen_server.call(pid, {:cache_env, env}, @timeout) end @doc false def get_cached_env(pid, ref) do :gen_server.call(pid, {:get_cached_env, ref}, @timeout) end # Stops the gen server @doc false def stop(pid) do :gen_server.cast(pid, :stop) end # Callbacks def init([]) do d = :digraph.new([:protected]) :digraph.add_vertex(d, :local) {:ok, {d, []}} end @doc false def handle_call({:cache_env, env}, _from, {d, cache}) do case cache do [{i, ^env}|_] -> {:reply, i, {d, cache}} t -> i = length(t) {:reply, i, {d, [{i, env}|t]}} end end def handle_call({:get_cached_env, ref}, _from, {_, cache} = state) do {^ref, env} = :lists.keyfind(ref, 1, cache) {:reply, env, state} end def handle_call({:yank, local}, _from, {d, _} = state) do out_vertices = :digraph.out_neighbours(d, local) :digraph.del_edges(d, :digraph.out_edges(d, local)) {:reply, {[], out_vertices}, state} end def handle_call(:digraph, _from, {d, _} = state) do {:reply, d, state} end @doc false def handle_info(_msg, state) do {:noreply, state} end def handle_cast({:add_local, from, to}, {d, _} = state) do handle_add_local(d, from, to) {:noreply, state} end def handle_cast({:add_import, function, module, {name, arity}}, {d, _} = state) do handle_import(d, function, module, name, arity) {:noreply, state} end def handle_cast({:add_definition, kind, tuple}, {d, _} = state) do handle_add_definition(d, kind, tuple) {:noreply, state} end def handle_cast({:add_defaults, kind, {name, arity}, defaults}, {d, _} = state) do for i <- :lists.seq(arity - defaults, arity - 1) do handle_add_definition(d, kind, {name, i}) handle_add_local(d, {name, i}, {name, i + 1}) end {:noreply, state} end def handle_cast({:reattach, _kind, tuple, {in_neigh, out_neigh}}, {d, _} = state) do for from <- in_neigh do :digraph.add_vertex(d, from) replace_edge!(d, from, tuple) end for to <- out_neigh do :digraph.add_vertex(d, to) replace_edge!(d, tuple, to) end {:noreply, state} end def handle_cast(:stop, state) do {:stop, :normal, state} end @doc false def terminate(_reason, _state) do :ok end @doc false def code_change(_old, state, _extra) do {:ok, state} end defp handle_import(d, function, module, name, arity) do :digraph.add_vertex(d, module) tuple = {:import, name, arity} :digraph.add_vertex(d, tuple) replace_edge!(d, tuple, module) if function != nil do replace_edge!(d, function, tuple) end :ok end defp handle_add_local(d, from, to) do :digraph.add_vertex(d, to) replace_edge!(d, from, to) end defp handle_add_definition(d, public, tuple) when public in [:def, :defmacro] do :digraph.add_vertex(d, tuple) replace_edge!(d, :local, tuple) end defp handle_add_definition(d, private, tuple) when private in [:defp, :defmacrop] do :digraph.add_vertex(d, tuple) end defp replace_edge!(d, from, to) do _ = unless :lists.member(to, :digraph.out_neighbours(d, from)) do [:"$e"|_] = :digraph.add_edge(d, from, to) end :ok end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/node.ex000066400000000000000000000162401254730255300212130ustar00rootroot00000000000000defmodule Node do @moduledoc """ Functions related to VM nodes. Some of the functions in this module are inlined by the compiler, similar to functions in the `Kernel` module and they are explicitly marked in their docs as "inlined by the compiler". For more information about inlined functions, check out the `Kernel` module. """ @type t :: node @doc """ Turns a non-distributed node into a distributed node. This functionality starts the `:net_kernel` and other related processes. """ @spec start(node, :longnames | :shortnames, non_neg_integer) :: {:ok, pid} | {:error, term} def start(name, type \\ :longnames, tick_time \\ 15000) do :net_kernel.start([name, type, tick_time]) end @doc """ Turns a distributed node into a non-distributed node. For other nodes in the network, this is the same as the node going down. Only possible when the node was started with `Node.start/3`, otherwise returns `{:error, :not_allowed}`. Returns `{:error, :not_found}` if the local node is not alive. """ @spec stop() :: :ok | {:error, :not_allowed | :not_found} def stop() do :net_kernel.stop() end @doc """ Returns the current node. It returns the same as the built-in `node()`. """ @spec self :: t def self do :erlang.node() end @doc """ Returns `true` if the local node is alive. That is, if the node can be part of a distributed system. """ @spec alive? :: boolean def alive? do :erlang.is_alive() end @doc """ Returns a list of all visible nodes in the system, excluding the local node. Same as `list(:visible)`. """ @spec list :: [t] def list do :erlang.nodes() end @doc """ Returns a list of nodes according to argument given. The result returned when the argument is a list, is the list of nodes satisfying the disjunction(s) of the list elements. See http://www.erlang.org/doc/man/erlang.html#nodes-1 for more info. """ @typep state :: :visible | :hidden | :connected | :this | :known @spec list(state | [state]) :: [t] def list(args) do :erlang.nodes(args) end @doc """ Monitors the status of the node. If `flag` is `true`, monitoring is turned on. If `flag` is `false`, monitoring is turned off. See http://www.erlang.org/doc/man/erlang.html#monitor_node-2 for more info. """ @spec monitor(t, boolean) :: true def monitor(node, flag) do :erlang.monitor_node(node, flag) end @doc """ Behaves as `monitor/2` except that it allows an extra option to be given, namely `:allow_passive_connect`. See http://www.erlang.org/doc/man/erlang.html#monitor_node-3 for more info. """ @spec monitor(t, boolean, [:allow_passive_connect]) :: true def monitor(node, flag, options) do :erlang.monitor_node(node, flag, options) end @doc """ Tries to set up a connection to node. Returns `:pang` if it fails, or `:pong` if it is successful. ## Examples iex> Node.ping(:unknown_node) :pang """ @spec ping(t) :: :pong | :pang def ping(node) do :net_adm.ping(node) end @doc """ Forces the disconnection of a node. This will appear to the `node` as if the local node has crashed. This function is mainly used in the Erlang network authentication protocols. Returns `true` if disconnection succeeds, otherwise `false`. If the local node is not alive, the function returns `:ignored`. See http://www.erlang.org/doc/man/erlang.html#disconnect_node-1 for more info. """ @spec disconnect(t) :: boolean | :ignored def disconnect(node) do :erlang.disconnect_node(node) end @doc """ Establishes a connection to `node`. Returns `true` if successful, `false` if not, and the atom `:ignored` if the local node is not alive. See http://erlang.org/doc/man/net_kernel.html#connect_node-1 for more info. """ @spec connect(t) :: boolean | :ignored def connect(node) do :net_kernel.connect_node(node) end @doc """ Returns the pid of a new process started by the application of `fun` on `node`. If `node` does not exist, a useless pid is returned. Check http://www.erlang.org/doc/man/erlang.html#spawn-2 for the list of available options. Inlined by the compiler. """ @spec spawn(t, (() -> any)) :: pid def spawn(node, fun) do :erlang.spawn(node, fun) end @doc """ Returns the pid of a new process started by the application of `fun` on `node`. If `node` does not exist, a useless pid is returned. Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-3 for the list of available options. Inlined by the compiler. """ @spec spawn(t, (() -> any), Process.spawn_opts) :: pid | {pid, reference} def spawn(node, fun, opts) do :erlang.spawn_opt(node, fun, opts) end @doc """ Returns the pid of a new process started by the application of `module.function(args)` on `node`. If `node` does not exist, a useless pid is returned. Check http://www.erlang.org/doc/man/erlang.html#spawn-4 for the list of available options. Inlined by the compiler. """ @spec spawn(t, module, atom, [any]) :: pid def spawn(node, module, fun, args) do :erlang.spawn(node, module, fun, args) end @doc """ Returns the pid of a new process started by the application of `module.function(args)` on `node`. If `node` does not exist, a useless pid is returned. Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-5 for the list of available options. Inlined by the compiler. """ @spec spawn(t, module, atom, [any], Process.spawn_opts) :: pid | {pid, reference} def spawn(node, module, fun, args, opts) do :erlang.spawn_opt(node, module, fun, args, opts) end @doc """ Returns the pid of a new linked process started by the application of `fun` on `node`. A link is created between the calling process and the new process, atomically. If `node` does not exist, a useless pid is returned (and due to the link, an exit signal with exit reason `:noconnection` will be received). Inlined by the compiler. """ @spec spawn_link(t, (() -> any)) :: pid def spawn_link(node, fun) do :erlang.spawn_link(node, fun) end @doc """ Returns the pid of a new linked process started by the application of `module.function(args)` on `node`. A link is created between the calling process and the new process, atomically. If `node` does not exist, a useless pid is returned (and due to the link, an exit signal with exit reason `:noconnection` will be received). Inlined by the compiler. """ @spec spawn_link(t, module, atom, [any]) :: pid def spawn_link(node, module, fun, args) do :erlang.spawn_link(node, module, fun, args) end @doc """ Sets the magic cookie of `node` to the atom `cookie`. The default node is `Node.self`, the local node. If `node` is the local node, the function also sets the cookie of all other unknown nodes to `cookie`. This function will raise `FunctionClauseError` if the given `node` is not alive. """ def set_cookie(node \\ Node.self, cookie) when is_atom(cookie) do :erlang.set_cookie(node, cookie) end @doc """ Returns the magic cookie of the local node. Returns the cookie if the node is alive, otherwise `:nocookie`. """ def get_cookie() do :erlang.get_cookie() end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/option_parser.ex000066400000000000000000000345331254730255300231570ustar00rootroot00000000000000defmodule OptionParser do @moduledoc """ This module contains functions to parse command line arguments. """ @type argv :: [String.t] @type parsed :: Keyword.t @type errors :: [{String.t, String.t | nil}] @type options :: [switches: Keyword.t, strict: Keyword.t, aliases: Keyword.t] @doc """ Parses `argv` into a keywords list. It returns the parsed values, remaining arguments and the invalid options. ## Examples iex> OptionParser.parse(["--debug"]) {[debug: true], [], []} iex> OptionParser.parse(["--source", "lib"]) {[source: "lib"], [], []} iex> OptionParser.parse(["--source-path", "lib", "test/enum_test.exs", "--verbose"]) {[source_path: "lib", verbose: true], ["test/enum_test.exs"], []} By default, Elixir will try to automatically parse switches. Switches without an argument, like `--debug` will automatically be set to `true`. Switches followed by a value will be assigned to the value, always as strings. Note Elixir also converts the switches to underscore atoms, as `--source-path` becomes `:source_path`, to better suit Elixir conventions. This means that option names on the command line cannot contain underscores; such options will be reported as `:undefined` (in strict mode) or `:invalid` (in basic mode). ## Switches Many times though, it is better to explicitly list the available switches and their formats. The switches can be specified via two different options: * `:strict` - the switches are strict. Any switch that does not exist in the switch list is treated as an error. * `:switches` - defines some switches. Switches that does not exist in the switch list are still attempted to be parsed. Note only `:strict` or `:switches` may be given at once. For each switch, the following types are supported: * `:boolean` - marks the given switch as a boolean. Boolean switches never consume the following value unless it is `true` or `false`. * `:integer` - parses the switch as an integer. * `:float` - parses the switch as a float. * `:string` - returns the switch as a string. If a switch can't be parsed or is not specified in the strict case, the option is returned in the invalid options list (third element of the returned tuple). The following extra "types" are supported: * `:keep` - keeps duplicated items in the list instead of overriding Examples: iex> OptionParser.parse(["--unlock", "path/to/file"], strict: [unlock: :boolean]) {[unlock: true], ["path/to/file"], []} iex> OptionParser.parse(["--unlock", "--limit", "0", "path/to/file"], ...> strict: [unlock: :boolean, limit: :integer]) {[unlock: true, limit: 0], ["path/to/file"], []} iex> OptionParser.parse(["--limit", "3"], strict: [limit: :integer]) {[limit: 3], [], []} iex> OptionParser.parse(["--limit", "xyz"], strict: [limit: :integer]) {[], [], [{"--limit", "xyz"}]} iex> OptionParser.parse(["--unknown", "xyz"], strict: []) {[], ["xyz"], [{"--unknown", nil}]} iex> OptionParser.parse(["--limit", "3", "--unknown", "xyz"], ...> switches: [limit: :integer]) {[limit: 3, unknown: "xyz"], [], []} ## Negation switches In case a switch is declared as boolean, it may be passed as `--no-SWITCH` which will set the option to `false`: iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean]) {[op: false], ["path/to/file"], []} ## Aliases A set of aliases can be given as options too: iex> OptionParser.parse(["-d"], aliases: [d: :debug]) {[debug: true], [], []} """ @spec parse(argv, options) :: {parsed, argv, errors} def parse(argv, opts \\ []) when is_list(argv) and is_list(opts) do do_parse(argv, compile_config(opts), [], [], [], true) end @doc """ Similar to `parse/2` but only parses the head of `argv`; as soon as it finds a non-switch, it stops parsing. See `parse/2` for more information. ## Example iex> OptionParser.parse_head(["--source", "lib", "test/enum_test.exs", "--verbose"]) {[source: "lib"], ["test/enum_test.exs", "--verbose"], []} iex> OptionParser.parse_head(["--verbose", "--source", "lib", "test/enum_test.exs", "--unlock"]) {[verbose: true, source: "lib"], ["test/enum_test.exs", "--unlock"], []} """ @spec parse_head(argv, options) :: {parsed, argv, errors} def parse_head(argv, opts \\ []) when is_list(argv) and is_list(opts) do do_parse(argv, compile_config(opts), [], [], [], false) end defp do_parse([], _config, opts, args, invalid, _all?) do {Enum.reverse(opts), Enum.reverse(args), Enum.reverse(invalid)} end defp do_parse(argv, {aliases, switches, strict}=config, opts, args, invalid, all?) do case next(argv, aliases, switches, strict) do {:ok, option, value, rest} -> # the option exist and it was successfully parsed kinds = List.wrap Keyword.get(switches, option) new_opts = do_store_option(opts, option, value, kinds) do_parse(rest, config, new_opts, args, invalid, all?) {:invalid, option, value, rest} -> # the option exist but it has wrong value do_parse(rest, config, opts, args, [{option, value}|invalid], all?) {:undefined, option, _value, rest} -> # the option does not exist (for strict cases) do_parse(rest, config, opts, args, [{option, nil}|invalid], all?) {:error, ["--"|rest]} -> {Enum.reverse(opts), Enum.reverse(args, rest), Enum.reverse(invalid)} {:error, [arg|rest]=remaining_args} -> # there is no option if all? do do_parse(rest, config, opts, [arg|args], invalid, all?) else {Enum.reverse(opts), Enum.reverse(args, remaining_args), Enum.reverse(invalid)} end end end @doc """ Low-level function that parses one option. It accepts the same options as `parse/2` and `parse_head/2` as both functions are built on top of next. This function may return: * `{:ok, key, value, rest}` - the option `key` with `value` was successfully parsed * `{:invalid, key, value, rest}` - the option `key` is invalid with `value` (returned when the switch type does not match the one given via the command line) * `{:undefined, key, value, rest}` - the option `key` is undefined (returned on strict cases and the switch is unknown) * `{:error, rest}` - there are no switches at the top of the given argv """ @spec next(argv, options) :: {:ok, key :: atom, value :: term, argv} | {:invalid, String.t, String.t | nil, argv} | {:undefined, String.t, String.t | nil, argv} | {:error, argv} def next(argv, opts \\ []) when is_list(argv) and is_list(opts) do {aliases, switches, strict} = compile_config(opts) next(argv, aliases, switches, strict) end defp next([], _aliases, _switches, _strict) do {:error, []} end defp next(["--"|_]=argv, _aliases, _switches, _strict) do {:error, argv} end defp next(["-"|_]=argv, _aliases, _switches, _strict) do {:error, argv} end defp next(["- " <> _|_]=argv, _aliases, _switches, _strict) do {:error, argv} end defp next(["-" <> option|rest], aliases, switches, strict) do {option, value} = split_option(option) opt_name_bin = "-" <> option tagged = tag_option(option, switches, aliases) if strict and not option_defined?(tagged, switches) do {:undefined, opt_name_bin, value, rest} else {opt_name, kinds, value} = normalize_option(tagged, value, switches) {value, kinds, rest} = normalize_value(value, kinds, rest, strict) case validate_option(value, kinds) do {:ok, new_value} -> {:ok, opt_name, new_value, rest} :invalid -> {:invalid, opt_name_bin, value, rest} end end end defp next(argv, _aliases, _switches, _strict) do {:error, argv} end @doc """ Receives a key-value enumerable and convert it to argv. Keys must be atoms. Keys with nil value are discarded, boolean values are converted to `--key` or `--no-key` and all other values are converted using `to_string/1`. ## Examples iex> OptionParser.to_argv([foo_bar: "baz"]) ["--foo-bar", "baz"] iex> OptionParser.to_argv([bool: true, bool: false, discarded: nil]) ["--bool", "--no-bool"] """ @spec to_argv(Enumerable.t) :: argv def to_argv(enum) do Enum.flat_map(enum, fn {_key, nil} -> [] {key, true} -> [to_switch(key)] {key, false} -> [to_switch(key, "--no-")] {key, value} -> [to_switch(key), to_string(value)] end) end defp to_switch(key, prefix \\ "--") when is_atom(key) do prefix <> String.replace(Atom.to_string(key), "_", "-") end @doc ~S""" Splits a string into argv chunks. ## Examples iex> OptionParser.split("foo bar") ["foo", "bar"] iex> OptionParser.split("foo \"bar baz\"") ["foo", "bar baz"] """ @spec split(String.t) :: argv def split(string) do do_split(strip_leading_spaces(string), "", [], nil) end # If we have a escaped quote, simply remove the escape defp do_split(<>, buffer, acc, quote), do: do_split(t, <>, acc, quote) # If we have a quote and we were not in a quote, start one defp do_split(<>, buffer, acc, nil) when quote in [?", ?'], do: do_split(t, buffer, acc, quote) # If we have a quote and we were inside it, close it defp do_split(<>, buffer, acc, quote), do: do_split(t, buffer, acc, nil) # If we have a escaped quote/space, simply remove the escape as long as we are not inside a quote defp do_split(<>, buffer, acc, nil) when h in [?\s, ?', ?"], do: do_split(t, <>, acc, nil) # If we have space and we are outside of a quote, start new segment defp do_split(<>, buffer, acc, nil), do: do_split(strip_leading_spaces(t), "", [buffer|acc], nil) # All other characters are moved to buffer defp do_split(<>, buffer, acc, quote) do do_split(t, <>, acc, quote) end # Finish the string expecting a nil marker defp do_split(<<>>, "", acc, nil), do: Enum.reverse(acc) defp do_split(<<>>, buffer, acc, nil), do: Enum.reverse([buffer|acc]) # Otherwise raise defp do_split(<<>>, _, _acc, marker) do raise "argv string did not terminate properly, a #{<>} was opened but never closed" end defp strip_leading_spaces(" " <> t), do: strip_leading_spaces(t) defp strip_leading_spaces(t), do: t ## Helpers defp compile_config(opts) do aliases = opts[:aliases] || [] {switches, strict} = cond do s = opts[:switches] -> {s, false} s = opts[:strict] -> {s, true} true -> {[], false} end {aliases, switches, strict} end defp validate_option(value, kinds) do {is_invalid, value} = cond do :invalid in kinds -> {true, value} :boolean in kinds -> case value do t when t in [true, "true"] -> {nil, true} f when f in [false, "false"] -> {nil, false} _ -> {true, value} end :integer in kinds -> case Integer.parse(value) do {value, ""} -> {nil, value} _ -> {true, value} end :float in kinds -> case Float.parse(value) do {value, ""} -> {nil, value} _ -> {true, value} end true -> {nil, value} end if is_invalid do :invalid else {:ok, value} end end defp do_store_option(dict, option, value, kinds) do cond do :keep in kinds -> [{option, value}|dict] true -> [{option, value}|Keyword.delete(dict, option)] end end defp tag_option(<>, switches, _aliases) do get_negated(option, switches) end defp tag_option(option, _switches, aliases) when is_binary(option) do opt = get_option(option) if alias = aliases[opt] do {:default, alias} else :unknown end end defp option_defined?(:unknown, _switches) do false end defp option_defined?({:negated, option}, switches) do Keyword.has_key?(switches, option) end defp option_defined?({:default, option}, switches) do Keyword.has_key?(switches, option) end defp normalize_option(:unknown, value, _switches) do {nil, [:invalid], value} end defp normalize_option({:negated, option}, value, switches) do if value do {option, [:invalid], value} else {option, List.wrap(switches[option]), false} end end defp normalize_option({:default, option}, value, switches) do {option, List.wrap(switches[option]), value} end defp normalize_value(nil, kinds, t, strict) do nil_or_true = if strict, do: nil, else: true cond do :boolean in kinds -> {true, kinds, t} value_in_tail?(t) -> [h|t] = t {h, kinds, t} kinds == [] -> {nil_or_true, kinds, t} true -> {nil, [:invalid], t} end end defp normalize_value(value, kinds, t, _) do {value, kinds, t} end defp value_in_tail?(["-"|_]), do: true defp value_in_tail?(["- " <> _|_]), do: true defp value_in_tail?(["-" <> _|_]), do: false defp value_in_tail?([]), do: false defp value_in_tail?(_), do: true defp split_option(option) do case :binary.split(option, "=") do [h] -> {h, nil} [h, t] -> {h, t} end end defp to_underscore(option), do: to_underscore(option, <<>>) defp to_underscore("_" <> _rest, _acc), do: nil defp to_underscore("-" <> rest, acc), do: to_underscore(rest, acc <> "_") defp to_underscore(<> <> rest, acc), do: to_underscore(rest, <>) defp to_underscore(<<>>, acc), do: acc defp get_option(option) do if str = to_underscore(option) do String.to_atom(str) end end defp get_negated("no-" <> rest = original, switches) do cond do (negated = get_option(rest)) && :boolean in List.wrap(switches[negated]) -> {:negated, negated} option = get_option(original) -> {:default, option} true -> :unknown end end defp get_negated(rest, _switches) do if option = get_option(rest) do {:default, option} else :unknown end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/path.ex000066400000000000000000000432731254730255300212300ustar00rootroot00000000000000defmodule Path do @moduledoc """ This module provides conveniences for manipulating or retrieving file system paths. The functions in this module may receive a char data as argument (i.e. a string or a list of characters / string) and will always return a string (encoded in UTF-8). The majority of the functions in this module do not interact with the file system, except for a few functions that require it (like `wildcard/1` and `expand/1`). """ alias :filename, as: FN @type t :: :unicode.chardata() @doc """ Converts the given path to an absolute one. Unlike `expand/1`, no attempt is made to resolve `..`, `.` or `~`. ## Unix examples Path.absname("foo") #=> "/usr/local/foo" Path.absname("../x") #=> "/usr/local/../x" ## Windows Path.absname("foo"). "D:/usr/local/foo" Path.absname("../x"). "D:/usr/local/../x" """ @spec absname(t) :: binary def absname(path) do absname(path, System.cwd!) end @doc """ Builds a path from `relative_to` to `path`. If `path` is already an absolute path, `relative_to` is ignored. See also `relative_to/2`. Unlike `expand/2`, no attempt is made to resolve `..`, `.` or `~`. ## Examples iex> Path.absname("foo", "bar") "bar/foo" iex> Path.absname("../x", "bar") "bar/../x" """ @spec absname(t, t) :: binary def absname(path, relative_to) do path = IO.chardata_to_string(path) case type(path) do :relative -> absname_join(relative_to, path) :absolute -> absname_join([path]) :volumerelative -> relative_to = IO.chardata_to_string(relative_to) absname_vr(split(path), split(relative_to), relative_to) end end # Absolute path on current drive defp absname_vr(["/"|rest], [volume|_], _relative), do: absname_join([volume|rest]) # Relative to current directory on current drive. defp absname_vr([<>|rest], [<>|_], relative), do: absname(absname_join(rest), relative) # Relative to current directory on another drive. defp absname_vr([<>|name], _, _relative) do cwd = case :file.get_cwd([x, ?:]) do {:ok, dir} -> IO.chardata_to_string(dir) {:error, _} -> <> end absname(absname_join(name), cwd) end # Joins a list defp absname_join([name1, name2|rest]), do: absname_join([absname_join(name1, name2)|rest]) defp absname_join([name]), do: do_absname_join(IO.chardata_to_string(name), <<>>, [], major_os_type()) # Joins two paths defp absname_join(left, right), do: do_absname_join(IO.chardata_to_string(left), relative(right), [], major_os_type()) defp do_absname_join(<>, relativename, [], :win32) when uc_letter in ?A..?Z, do: do_absname_join(rest, relativename, [?:, uc_letter+?a-?A], :win32) defp do_absname_join(<>, relativename, result, :win32), do: do_absname_join(<>, relativename, result, :win32) defp do_absname_join(<>, relativename, [?., ?/|result], os_type), do: do_absname_join(rest, relativename, [?/|result], os_type) defp do_absname_join(<>, relativename, [?/|result], os_type), do: do_absname_join(rest, relativename, [?/|result], os_type) defp do_absname_join(<<>>, <<>>, result, os_type), do: IO.iodata_to_binary(reverse_maybe_remove_dirsep(result, os_type)) defp do_absname_join(<<>>, relativename, [?:|rest], :win32), do: do_absname_join(relativename, <<>>, [?:|rest], :win32) defp do_absname_join(<<>>, relativename, [?/|result], os_type), do: do_absname_join(relativename, <<>>, [?/|result], os_type) defp do_absname_join(<<>>, relativename, result, os_type), do: do_absname_join(relativename, <<>>, [?/|result], os_type) defp do_absname_join(<>, relativename, result, os_type), do: do_absname_join(rest, relativename, [char|result], os_type) defp reverse_maybe_remove_dirsep([?/, ?:, letter], :win32), do: [letter, ?:, ?/] defp reverse_maybe_remove_dirsep([?/], _), do: [?/] defp reverse_maybe_remove_dirsep([?/|name], _), do: :lists.reverse(name) defp reverse_maybe_remove_dirsep(name, _), do: :lists.reverse(name) @doc """ Converts the path to an absolute one and expands any `.` and `..` characters and a leading `~`. ## Examples Path.expand("/foo/bar/../bar") "/foo/bar" """ @spec expand(t) :: binary def expand(path) do expand_dot absname(expand_home(path), System.cwd!) end @doc """ Expands the path relative to the path given as the second argument expanding any `.` and `..` characters. If the path is already an absolute path, `relative_to` is ignored. Note, that this function treats `path` with a leading `~` as an absolute one. The second argument is first expanded to an absolute path. ## Examples # Assuming that the absolute path to baz is /quux/baz Path.expand("foo/bar/../bar", "baz") #=> "/quux/baz/foo/bar" Path.expand("foo/bar/../bar", "/baz") "/baz/foo/bar" Path.expand("/foo/bar/../bar", "/baz") "/foo/bar" """ @spec expand(t, t) :: binary def expand(path, relative_to) do expand_dot absname(absname(expand_home(path), expand_home(relative_to)), System.cwd!) end @doc """ Returns the path type. ## Unix examples Path.type("/") #=> :absolute Path.type("/usr/local/bin") #=> :absolute Path.type("usr/local/bin") #=> :relative Path.type("../usr/local/bin") #=> :relative Path.type("~/file") #=> :relative ## Windows examples Path.type("D:/usr/local/bin") #=> :absolute Path.type("usr/local/bin") #=> :relative Path.type("D:bar.ex") #=> :volumerelative Path.type("/bar/foo.ex") #=> :volumerelative """ @spec type(t) :: :absolute | :relative | :volumerelative def type(name) when is_list(name) or is_binary(name) do pathtype(name, major_os_type) |> elem(0) end @doc """ Forces the path to be a relative path. ## Unix examples Path.relative("/usr/local/bin") #=> "usr/local/bin" Path.relative("usr/local/bin") #=> "usr/local/bin" Path.relative("../usr/local/bin") #=> "../usr/local/bin" ## Windows examples Path.relative("D:/usr/local/bin") #=> "usr/local/bin" Path.relative("usr/local/bin") #=> "usr/local/bin" Path.relative("D:bar.ex") #=> "bar.ex" Path.relative("/bar/foo.ex") #=> "bar/foo.ex" """ @spec relative(t) :: binary def relative(name) do relative(name, major_os_type()) end defp relative(name, os_type) do pathtype(name, os_type) |> elem(1) |> IO.chardata_to_string end defp pathtype(name, os_type) do case os_type do :win32 -> win32_pathtype(name) _ -> unix_pathtype(name) end end defp unix_pathtype(<>), do: {:absolute, relative} defp unix_pathtype([?/|relative]), do: {:absolute, relative} defp unix_pathtype([list|rest]) when is_list(list), do: unix_pathtype(list ++ rest) defp unix_pathtype(relative), do: {:relative, relative} @slash [?/, ?\\] defp win32_pathtype([list|rest]) when is_list(list), do: win32_pathtype(list++rest) defp win32_pathtype([char, list|rest]) when is_list(list), do: win32_pathtype([char|list++rest]) defp win32_pathtype(<>) when c1 in @slash and c2 in @slash, do: {:absolute, relative} defp win32_pathtype(<>) when c in @slash, do: {:volumerelative, relative} defp win32_pathtype(<<_letter, ?:, c, relative :: binary>>) when c in @slash, do: {:absolute, relative} defp win32_pathtype(<<_letter, ?:, relative :: binary>>), do: {:volumerelative, relative} defp win32_pathtype([c1, c2 | relative]) when c1 in @slash and c2 in @slash, do: {:absolute, relative} defp win32_pathtype([c | relative]) when c in @slash, do: {:volumerelative, relative} defp win32_pathtype([c1, c2, list|rest]) when is_list(list), do: win32_pathtype([c1, c2|list++rest]) defp win32_pathtype([_letter, ?:, c | relative]) when c in @slash, do: {:absolute, relative} defp win32_pathtype([_letter, ?: | relative]), do: {:volumerelative, relative} defp win32_pathtype(relative), do: {:relative, relative} @doc """ Returns the given `path` relative to the given `from` path. In other words, it tries to strip the `from` prefix from `path`. This function does not query the file system, so it assumes no symlinks between the paths. In case a direct relative path cannot be found, it returns the original path. ## Examples iex> Path.relative_to("/usr/local/foo", "/usr/local") "foo" iex> Path.relative_to("/usr/local/foo", "/") "usr/local/foo" iex> Path.relative_to("/usr/local/foo", "/etc") "/usr/local/foo" """ @spec relative_to(t, t) :: binary def relative_to(path, from) do path = IO.chardata_to_string(path) relative_to(split(path), split(from), path) end defp relative_to([h|t1], [h|t2], original) do relative_to(t1, t2, original) end defp relative_to([_|_] = l1, [], _original) do join(l1) end defp relative_to(_, _, original) do original end @doc """ Convenience to get the path relative to the current working directory. If, for some reason, the current working directory cannot be retrieved, returns the full path. """ @spec relative_to_cwd(t) :: binary def relative_to_cwd(path) do case :file.get_cwd do {:ok, base} -> relative_to(path, IO.chardata_to_string(base)) _ -> path end end @doc """ Returns the last component of the path or the path itself if it does not contain any directory separators. ## Examples iex> Path.basename("foo") "foo" iex> Path.basename("foo/bar") "bar" iex> Path.basename("/") "" """ @spec basename(t) :: binary def basename(path) do FN.basename(IO.chardata_to_string(path)) end @doc """ Returns the last component of `path` with the `extension` stripped. This function should be used to remove a specific extension which may, or may not, be there. ## Examples iex> Path.basename("~/foo/bar.ex", ".ex") "bar" iex> Path.basename("~/foo/bar.exs", ".ex") "bar.exs" iex> Path.basename("~/foo/bar.old.ex", ".ex") "bar.old" """ @spec basename(t, t) :: binary def basename(path, extension) do FN.basename(IO.chardata_to_string(path), IO.chardata_to_string(extension)) end @doc """ Returns the directory component of `path`. ## Examples Path.dirname("/foo/bar.ex") #=> "/foo" Path.dirname("/foo/bar/baz.ex") #=> "/foo/bar" """ @spec dirname(t) :: binary def dirname(path) do FN.dirname(IO.chardata_to_string(path)) end @doc """ Returns the extension of the last component of `path`. ## Examples iex> Path.extname("foo.erl") ".erl" iex> Path.extname("~/foo/bar") "" """ @spec extname(t) :: binary def extname(path) do FN.extension(IO.chardata_to_string(path)) end @doc """ Returns the `path` with the `extension` stripped. ## Examples iex> Path.rootname("/foo/bar") "/foo/bar" iex> Path.rootname("/foo/bar.ex") "/foo/bar" """ @spec rootname(t) :: binary def rootname(path) do FN.rootname(IO.chardata_to_string(path)) end @doc """ Returns the `path` with the `extension` stripped. This function should be used to remove a specific extension which might, or might not, be there. ## Examples iex> Path.rootname("/foo/bar.erl", ".erl") "/foo/bar" iex> Path.rootname("/foo/bar.erl", ".ex") "/foo/bar.erl" """ @spec rootname(t, t) :: binary def rootname(path, extension) do FN.rootname(IO.chardata_to_string(path), IO.chardata_to_string(extension)) end @doc """ Joins a list of strings. This function should be used to convert a list of strings to a path. Note that any trailing slash is removed on join. ## Examples iex> Path.join(["~", "foo"]) "~/foo" iex> Path.join(["foo"]) "foo" iex> Path.join(["/", "foo", "bar/"]) "/foo/bar" """ @spec join([t]) :: binary def join([name1, name2|rest]), do: join([join(name1, name2)|rest]) def join([name]), do: name @doc """ Joins two paths. The right path will always be expanded to its relative format and any trailing slash is removed on join. ## Examples iex> Path.join("foo", "bar") "foo/bar" """ @spec join(t, t) :: binary def join(left, right) do left = IO.chardata_to_string(left) os_type = major_os_type() do_join(left, right, os_type) |> remove_dirsep(os_type) end defp do_join("", right, os_type), do: relative(right, os_type) defp do_join(left, "", _os_type), do: left defp do_join(left, right, os_type), do: remove_dirsep(left, os_type) <> "/" <> relative(right, os_type) defp remove_dirsep("", _os_type), do: "" defp remove_dirsep(bin, os_type) do last = :binary.last(bin) if last == ?/ or (last == ?\\ and os_type == :win32) do binary_part(bin, 0, byte_size(bin) - 1) else bin end end @doc ~S""" Splits the path into a list at the path separator. If an empty string is given, returns an empty list. On Windows, path is split on both "\" and "/" separators and the driver letter, if there is one, is always returned in lowercase. ## Examples iex> Path.split("") [] iex> Path.split("foo") ["foo"] iex> Path.split("/foo/bar") ["/", "foo", "bar"] """ @spec split(t) :: [binary] # Work around a bug in Erlang on UNIX def split(""), do: [] def split(path) do FN.split(IO.chardata_to_string(path)) end defmodule Wildcard do @moduledoc false def read_link_info(file) do call({:read_link_info, file}) end # For compatibility with buggy Erlang 17.1. def read_file_info(file) do call({:read_link_info, file}) end def list_dir(dir) do case call({:list_dir, dir}) do {:ok, files} -> {:ok, for(file <- files, hd(file) != ?., do: file)} other -> other end end @compile {:inline, call: 1} defp call(tuple) do x = :erlang.dt_spread_tag(true) y = :gen_server.call(:file_server_2, tuple) :erlang.dt_restore_tag(x) y end end @doc """ Traverses paths according to the given `glob` expression, and returns a list of matches. The wildcard looks like an ordinary path, except that certain "wildcard characters" are interpreted in a special way. The following characters are special: * `?` - matches one character * `*` - matches any number of characters up to the end of the filename, the next dot, or the next slash * `**` - two adjacent `*`'s used as a single pattern will match all files and zero or more directories and subdirectories * `[char1, char2, ...]` - matches any of the characters listed; two characters separated by a hyphen will match a range of characters * `{item1, item2, ...}` - matches one of the alternatives Other characters represent themselves. Only paths that have exactly the same character in the same position will match. Note that matching is case-sensitive; i.e. "a" will not match "A". By default, the patterns `*` and `?` do not match files starting with a dot `.` unless `match_dot: true` is given in `opts`. ## Examples Imagine you have a directory called `projects` with three Elixir projects inside of it: `elixir`, `ex_doc` and `dynamo`. You can find all `.beam` files inside the `ebin` directory of each project as follows: Path.wildcard("projects/*/ebin/**/*.beam") If you want to search for both `.beam` and `.app` files, you could do: Path.wildcard("projects/*/ebin/**/*.{beam,app}") """ @spec wildcard(t, Keyword.t) :: [binary] def wildcard(glob, opts \\ []) do mod = if Keyword.get(opts, :match_dot), do: :file, else: Path.Wildcard glob |> chardata_to_list() |> :filelib.wildcard(mod) |> Enum.map(&IO.chardata_to_string/1) end # expand_dot the given path by expanding "..", "." and "~". defp chardata_to_list(chardata) do case :unicode.characters_to_list(chardata) do result when is_list(result) -> result {:error, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :invalid {:incomplete, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :incomplete end end defp expand_home(type) do case IO.chardata_to_string(type) do "~" <> rest -> resolve_home(rest) rest -> rest end end defp resolve_home(""), do: System.user_home! defp resolve_home(rest) do case {rest, major_os_type} do {"\\" <> _, :win32} -> System.user_home! <> rest {"/" <> _, _} -> System.user_home! <> rest _ -> rest end end defp expand_dot(<<"/../", rest::binary>>), do: expand_dot("/" <> rest) defp expand_dot(<>) when letter in ?a..?z, do: expand_dot(<>) defp expand_dot("/.."), do: "/" defp expand_dot(<>) when letter in ?a..?z, do: expand_dot(<>) defp expand_dot(path), do: expand_dot(:binary.split(path, "/", [:global]), []) defp expand_dot([".."|t], [_, _|acc]) do expand_dot t, acc end defp expand_dot(["."|t], acc) do expand_dot t, acc end defp expand_dot([h|t], acc) do expand_dot t, ["/", h|acc] end defp expand_dot([], ["/"|acc]) do IO.iodata_to_binary(:lists.reverse(acc)) end defp major_os_type do :os.type |> elem(0) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/port.ex000066400000000000000000000041421254730255300212500ustar00rootroot00000000000000defmodule Port do @moduledoc """ Functions related to Erlang ports. """ @doc """ See http://www.erlang.org/doc/man/erlang.html#open_port-2. Inlined by the compiler. """ def open(name, settings) do :erlang.open_port(name, settings) end @doc """ See http://www.erlang.org/doc/man/erlang.html#port_close-1. Inlined by the compiler. """ def close(port) do :erlang.port_close(port) end @doc """ See http://www.erlang.org/doc/man/erlang.html#port_command-2. Inlined by the compiler. """ def command(port, data, options \\ []) do :erlang.port_command(port, data, options) end @doc """ See http://www.erlang.org/doc/man/erlang.html#port_connect-2. Inlined by the compiler. """ def connect(port, pid) do :erlang.port_connect(port, pid) end @doc """ See http://www.erlang.org/doc/man/erlang.html#port_control-3. Inlined by the compiler. """ def control(port, operation, data) do :erlang.port_control(port, operation, data) end @doc """ See http://www.erlang.org/doc/man/erlang.html#port_call-3. Inlined by the compiler. """ def call(port, operation, data) do :erlang.port_call(port, operation, data) end @doc """ Returns information about the `port` or `nil` if the port is closed. See http://www.erlang.org/doc/man/erlang.html#port_info-1. """ def info(port) do nillify :erlang.port_info(port) end @doc """ Returns information about the `port` or `nil` if the port is closed. See http://www.erlang.org/doc/man/erlang.html#port_info-2. """ @spec info(port, atom) :: {atom, term} | nil def info(port, spec) def info(port, :registered_name) do case :erlang.port_info(port, :registered_name) do [] -> {:registered_name, []} other -> nillify(other) end end def info(port, item) do nillify :erlang.port_info(port, item) end @doc """ See http://www.erlang.org/doc/man/erlang.html#ports-0. Inlined by the compiler. """ def list do :erlang.ports end @compile {:inline, nillify: 1} defp nillify(:undefined), do: nil defp nillify(other), do: other end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/process.ex000066400000000000000000000300161254730255300217410ustar00rootroot00000000000000defmodule Process do @moduledoc """ Conveniences for working with processes and the process dictionary. Besides the functions available in this module, the `Kernel` module exposes and auto-imports some basic functionality related to processes available through the functions: * `Kernel.spawn/1` and `Kernel.spawn/3` * `Kernel.spawn_link/1` and `Kernel.spawn_link/3` * `Kernel.spawn_monitor/1` and `Kernel.spawn_monitor/3` * `Kernel.self/0` * `Kernel.send/2` """ @doc """ Returns `true` if the process exists and is alive, that is, is not exiting and has not exited. Otherwise, returns `false`. `pid` must refer to a process at the local node. """ @spec alive?(pid) :: boolean def alive?(pid) do :erlang.is_process_alive(pid) end @doc """ Returns all key-values in the dictionary. """ @spec get :: [{term, term}] def get do :erlang.get() end @doc """ Returns the value for the given `key`. """ @spec get(term) :: term @spec get(term, default :: term) :: term def get(key, default \\ nil) do case :erlang.get(key) do :undefined -> default value -> value end end @doc """ Returns all keys that have the given `value`. """ @spec get_keys(term) :: [term] def get_keys(value) do :erlang.get_keys(value) end @doc """ Stores the given key-value in the process dictionary. """ @spec put(term, term) :: term | nil def put(key, value) do nillify :erlang.put(key, value) end @doc """ Deletes the given `key` from the dictionary. """ @spec delete(term) :: term | nil def delete(key) do nillify :erlang.erase(key) end @doc """ Sends an exit signal with the given reason to the pid. The following behaviour applies if reason is any term except `:normal` or `:kill`: 1. If pid is not trapping exits, pid will exit with the given reason. 2. If pid is trapping exits, the exit signal is transformed into a message `{:EXIT, from, reason}` and delivered to the message queue of pid. 3. If reason is the atom `:normal`, pid will not exit (unless it is the calling process's pid, in which case it will exit with the reason `:normal`). If it is trapping exits, the exit signal is transformed into a message `{:EXIT, from, :normal}` and delivered to its message queue. 4. If reason is the atom `:kill`, that is if `exit(pid, :kill)` is called, an untrappable exit signal is sent to pid which will unconditionally exit with exit reason `:killed`. Inlined by the compiler. ## Examples Process.exit(pid, :kill) """ @spec exit(pid, term) :: true def exit(pid, reason) do :erlang.exit(pid, reason) end @doc """ Sends a message to the given process. If the option `:noconnect` is used and sending the message would require an auto-connection to another node the message is not sent and `:noconnect` is returned. If the option `:nosuspend` is used and sending the message would cause the sender to be suspended the message is not sent and `:nosuspend` is returned. Otherwise the message is sent and `:ok` is returned. ## Examples iex> Process.send({:name, :node_does_not_exist}, :hi, [:noconnect]) :noconnect """ @spec send(dest, msg, [option]) :: result when dest: pid | port | atom | {atom, node}, msg: any, option: :noconnect | :nosuspend, result: :ok | :noconnect | :nosuspend def send(dest, msg, options) do :erlang.send(dest, msg, options) end @doc """ Sends `msg` to `dest` after `time` milliseconds. If `dest` is a pid, it must be the pid of a local process, dead or alive. If `dest` is an atom, it must be the name of a registered process which is looked up at the time of delivery. No error is given if the name does not refer to a process. This function returns a timer reference, which can be read or canceled with `:erlang.read_timer/1`, `:erlang.start_timer/3` and `:erlang.cancel_timer/1`. Note `time` cannot be greater than `4294967295`. Finally, the timer will be automatically canceled if the given `dest` is a pid which is not alive or when the given pid exits. Note that timers will not be automatically canceled when `dest` is an atom (as the atom resolution is done on delivery). """ @spec send_after(pid | atom, term, non_neg_integer) :: reference def send_after(dest, msg, time) do :erlang.send_after(time, dest, msg) end @type spawn_opt :: :link | :monitor | {:priority, :low | :normal | :high} | {:fullsweep_after, non_neg_integer} | {:min_heap_size, non_neg_integer} | {:min_bin_vheap_size, non_neg_integer} @type spawn_opts :: [spawn_opt] @doc """ Spawns the given module and function passing the given args according to the given options. The result depends on the given options. In particular, if `:monitor` is given as an option, it will return a tuple containing the pid and the monitoring reference, otherwise just the spawned process pid. It also accepts extra options, for the list of available options check http://www.erlang.org/doc/man/erlang.html#spawn_opt-4 Inlined by the compiler. """ @spec spawn((() -> any), spawn_opts) :: pid | {pid, reference} def spawn(fun, opts) do :erlang.spawn_opt(fun, opts) end @doc """ Spawns the given module and function passing the given args according to the given options. The result depends on the given options. In particular, if `:monitor` is given as an option, it will return a tuple containing the pid and the monitoring reference, otherwise just the spawned process pid. It also accepts extra options, for the list of available options check http://www.erlang.org/doc/man/erlang.html#spawn_opt-4 Inlined by the compiler. """ @spec spawn(module, atom, list, spawn_opts) :: pid | {pid, reference} def spawn(mod, fun, args, opts) do :erlang.spawn_opt(mod, fun, args, opts) end @doc """ The calling process starts monitoring the item given. It returns the monitor reference. See http://www.erlang.org/doc/man/erlang.html#monitor-2 for more info. Inlined by the compiler. """ @spec monitor(pid | {reg_name :: atom, node :: atom} | reg_name :: atom) :: reference def monitor(item) do :erlang.monitor(:process, item) end @doc """ If `monitor_ref` is a reference which the calling process obtained by calling `monitor/1`, this monitoring is turned off. If the monitoring is already turned off, nothing happens. See http://www.erlang.org/doc/man/erlang.html#demonitor-2 for more info. Inlined by the compiler. """ @spec demonitor(reference) :: true @spec demonitor(reference, options :: [:flush | :info]) :: boolean def demonitor(monitor_ref, options \\ []) do :erlang.demonitor(monitor_ref, options) end @doc """ Returns a list of process identifiers corresponding to all the processes currently existing on the local node. Note that a process that is exiting, exists but is not alive, i.e., `alive?/1` will return `false` for a process that is exiting, but its process identifier will be part of the result returned. See http://www.erlang.org/doc/man/erlang.html#processes-0 for more info. """ @spec list :: [pid] def list do :erlang.processes() end @doc """ Creates a link between the calling process and another process (or port) `pid`, if there is not such a link already. See http://www.erlang.org/doc/man/erlang.html#link-1 for more info. Inlined by the compiler. """ @spec link(pid | port) :: true def link(pid) do :erlang.link(pid) end @doc """ Removes the link, if there is one, between the calling process and the process or port referred to by `pid`. Returns `true` and does not fail, even if there is no link or `id` does not exist See http://www.erlang.org/doc/man/erlang.html#unlink-1 for more info. Inlined by the compiler. """ @spec unlink(pid | port) :: true def unlink(pid) do :erlang.unlink(pid) end @doc """ Associates the name with a pid or a port identifier. `name`, which must be an atom, can be used instead of the pid / port identifier with the `Kernel.send/2` function. `Process.register/2` will fail with `ArgumentError` if the pid supplied is no longer alive, (check with `alive?/1`) or if the name is already registered (check with `whereis/1`). """ @spec register(pid | port, atom) :: true def register(pid, name) when not name in [nil, false, true] do :erlang.register(name, pid) end @doc """ Removes the registered name, associated with a pid or a port identifier. See http://www.erlang.org/doc/man/erlang.html#unregister-1 for more info. """ @spec unregister(atom) :: true def unregister(name) do :erlang.unregister(name) end @doc """ Returns the pid or port identifier with the registered name. Returns `nil` if the name is not registered. See http://www.erlang.org/doc/man/erlang.html#whereis-1 for more info. """ @spec whereis(atom) :: pid | port | nil def whereis(name) do nillify :erlang.whereis(name) end @doc """ Returns the pid of the group leader for the process which evaluates the function. """ @spec group_leader :: pid def group_leader do :erlang.group_leader end @doc """ Sets the group leader of `pid` to `leader`. Typically, this is used when a processes started from a certain shell should have a group leader other than `:init`. """ @spec group_leader(pid, leader :: pid) :: true def group_leader(pid, leader) do :erlang.group_leader(leader, pid) end @doc """ Returns a list of names which have been registered using `register/2`. """ @spec registered :: [atom] def registered do :erlang.registered() end @typep process_flag :: :trap_exit | :error_handler | :min_heap_size | :min_bin_vheap_size | :priority | :save_calls | :sensitive @doc """ Sets certain flags for the process which calls this function. Returns the old value of the flag. See http://www.erlang.org/doc/man/erlang.html#process_flag-2 for more info. """ @spec flag(process_flag, term) :: term def flag(flag, value) do :erlang.process_flag(flag, value) end @doc """ Sets certain flags for the process `pid`, in the same manner as `flag/2`. Returns the old value of the flag. The allowed values for `flag` are only a subset of those allowed in `flag/2`, namely: `save_calls`. See http://www.erlang.org/doc/man/erlang.html#process_flag-3 for more info. """ @spec flag(pid, :save_calls, non_neg_integer) :: non_neg_integer def flag(pid, flag, value) do :erlang.process_flag(pid, flag, value) end @doc """ Returns information about the process identified by `pid` or `nil` if the process is not alive. Use this only for debugging information. See http://www.erlang.org/doc/man/erlang.html#process_info-1 for more info. """ @spec info(pid) :: Keyword.t def info(pid) do nillify :erlang.process_info(pid) end @doc """ Returns information about the process identified by `pid` or `nil` if the process is not alive. See http://www.erlang.org/doc/man/erlang.html#process_info-2 for more info. """ @spec info(pid, atom) :: {atom, term} | nil def info(pid, spec) def info(pid, :registered_name) do case :erlang.process_info(pid, :registered_name) do :undefined -> nil [] -> {:registered_name, []} other -> other end end def info(pid, spec) when is_atom(spec) do nillify :erlang.process_info(pid, spec) end @doc """ Puts the calling process into a wait state where its memory allocation has been reduced as much as possible, which is useful if the process does not expect to receive any messages in the near future. See http://www.erlang.org/doc/man/erlang.html#hibernate-3 for more info. Inlined by the compiler. """ @spec hibernate(module, atom, list) :: no_return def hibernate(mod, fun, args) do :erlang.hibernate(mod, fun, args) end @compile {:inline, nillify: 1} defp nillify(:undefined), do: nil defp nillify(other), do: other end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/protocol.ex000066400000000000000000000464051254730255300221350ustar00rootroot00000000000000defmodule Protocol do @moduledoc """ Functions for working with protocols. """ @doc """ Defines a new protocol function. Protocols do not allow functions to be defined directly, instead, the regular `Kernel.def/*` macros are replaced by this macro which defines the protocol functions with the appropriate callbacks. """ defmacro def(signature) defmacro def({_, _, args}) when args == [] or is_atom(args) do raise ArgumentError, "protocol functions expect at least one argument" end defmacro def({name, _, args}) when is_atom(name) and is_list(args) do arity = length(args) type_args = :lists.map(fn _ -> quote(do: term) end, :lists.seq(2, arity)) type_args = [quote(do: t) | type_args] call_args = :lists.map(fn i -> {String.to_atom(<>), [], __MODULE__} end, :lists.seq(2, arity)) call_args = [quote(do: t) | call_args] quote do name = unquote(name) arity = unquote(arity) @functions [{name, arity}|@functions] # Generate a fake definition with the user # signature that will be used by docs Kernel.def unquote(name)(unquote_splicing(args)) # Generate the actual implementation Kernel.def unquote(name)(unquote_splicing(call_args)) do impl_for!(t).unquote(name)(unquote_splicing(call_args)) end # Convert the spec to callback if possible, # otherwise generate a dummy callback Protocol.__spec__?(__MODULE__, name, arity) || @callback unquote(name)(unquote_splicing(type_args)) :: term end end defmacro def(_) do raise ArgumentError, "invalid args for def inside defprotocol" end @doc """ Checks if the given module is loaded and is protocol. Returns `:ok` if so, otherwise raises ArgumentError. """ @spec assert_protocol!(module) :: :ok | no_return def assert_protocol!(module) do assert_protocol!(module, "") end defp assert_protocol!(module, extra) do case Code.ensure_compiled(module) do {:module, ^module} -> :ok _ -> raise ArgumentError, "#{inspect module} is not available" <> extra end try do module.__protocol__(:module) rescue UndefinedFunctionError -> raise ArgumentError, "#{inspect module} is not a protocol" <> extra end :ok end @doc """ Checks if the given module is loaded and is an implementation of the given protocol. Returns `:ok` if so, otherwise raises ArgumentError. """ @spec assert_impl!(module, module) :: :ok | no_return def assert_impl!(protocol, base) do assert_impl!(protocol, base, "") end defp assert_impl!(protocol, base, extra) do impl = Module.concat(protocol, base) case Code.ensure_compiled(impl) do {:module, ^impl} -> :ok _ -> raise ArgumentError, "#{inspect impl} is not available" <> extra end try do impl.__impl__(:protocol) rescue UndefinedFunctionError -> raise ArgumentError, "#{inspect impl} is not an implementation of a protocol" <> extra else ^protocol -> :ok other -> raise ArgumentError, "expected #{inspect impl} to be an implementation of #{inspect protocol}, got: #{inspect other}" <> extra end end @doc """ Derives the `protocol` for `module` with the given options. """ defmacro derive(protocol, module, options \\ []) do quote do module = unquote(module) Protocol.__derive__([{unquote(protocol), unquote(options)}], module, __ENV__) end end ## Consolidation @doc """ Extracts all protocols from the given paths. The paths can be either a char list or a string. Internally they are worked on as char lists, so passing them as lists avoid extra conversion. Does not load any of the protocols. ## Examples # Get Elixir's ebin and retrieve all protocols iex> path = :code.lib_dir(:elixir, :ebin) iex> mods = Protocol.extract_protocols([path]) iex> Enumerable in mods true """ @spec extract_protocols([char_list | String.t]) :: [atom] def extract_protocols(paths) do extract_matching_by_attribute paths, 'Elixir.', fn module, attributes -> case attributes[:protocol] do [fallback_to_any: _] -> module _ -> nil end end end @doc """ Extracts all types implemented for the given protocol from the given paths. The paths can be either a char list or a string. Internally they are worked on as char lists, so passing them as lists avoid extra conversion. Does not load any of the implementations. ## Examples # Get Elixir's ebin and retrieve all protocols iex> path = :code.lib_dir(:elixir, :ebin) iex> mods = Protocol.extract_impls(Enumerable, [path]) iex> List in mods true """ @spec extract_impls(module, [char_list | String.t]) :: [atom] def extract_impls(protocol, paths) when is_atom(protocol) do prefix = Atom.to_char_list(protocol) ++ '.' extract_matching_by_attribute paths, prefix, fn _mod, attributes -> case attributes[:impl] do [protocol: ^protocol, for: for] -> for _ -> nil end end end defp extract_matching_by_attribute(paths, prefix, callback) do for path <- paths, file <- list_dir(path), mod = extract_from_file(path, file, prefix, callback), do: mod end defp list_dir(path) when is_list(path) do case :file.list_dir(path) do {:ok, files} -> files _ -> [] end end defp list_dir(path), do: list_dir(to_char_list(path)) defp extract_from_file(path, file, prefix, callback) do if :lists.prefix(prefix, file) and :filename.extension(file) == '.beam' do extract_from_beam(:filename.join(path, file), callback) end end defp extract_from_beam(file, callback) do case :beam_lib.chunks(file, [:attributes]) do {:ok, {module, [attributes: attributes]}} -> callback.(module, attributes) _ -> nil end end defmacrop if_ok(expr, call) do quote do case unquote(expr) do {:ok, var} -> unquote(Macro.pipe(quote(do: var), call, 0)) other -> other end end end @doc """ Returns `true` if the protocol was consolidated. """ @spec consolidated?(module) :: boolean def consolidated?(protocol) do protocol.__protocol__(:consolidated?) end @doc """ Receives a protocol and a list of implementations and consolidates the given protocol. Consolidation happens by changing the protocol `impl_for` in the abstract format to have fast lookup rules. Usually the list of implementations to use during consolidation are retrieved with the help of `extract_impls/2`. It returns the updated version of the protocol bytecode. A given bytecode or protocol implementation can be checked to be consolidated or not by analyzing the protocol attribute: Protocol.consolidated?(Enumerable) If the first element of the tuple is `true`, it means the protocol was consolidated. This function does not load the protocol at any point nor loads the new bytecode for the compiled module. However each implementation must be available and it will be loaded. """ @spec consolidate(module, [module]) :: {:ok, binary} | {:error, :not_a_protocol} | {:error, :no_beam_info} def consolidate(protocol, types) when is_atom(protocol) do beam_protocol(protocol) |> if_ok(change_debug_info types) |> if_ok(compile) end @docs_chunk 'ExDc' defp beam_protocol(protocol) do chunk_ids = [:abstract_code, :attributes, @docs_chunk] opts = [:allow_missing_chunks] case :beam_lib.chunks(beam_file(protocol), chunk_ids, opts) do {:ok, {^protocol, [{:abstract_code, {_raw, abstract_code}}, {:attributes, attributes}, {@docs_chunk, docs}]}} -> case attributes[:protocol] do [fallback_to_any: any] -> {:ok, {protocol, any, abstract_code, docs}} _ -> {:error, :not_a_protocol} end _ -> {:error, :no_beam_info} end end defp beam_file(module) when is_atom(module) do case :code.which(module) do atom when is_atom(atom) -> module file -> file end end # Change the debug information to the optimized # impl_for/1 dispatch version. defp change_debug_info({protocol, any, code, docs}, types) do types = if any, do: types, else: List.delete(types, Any) all = [Any] ++ for {_guard, mod} <- builtin, do: mod structs = types -- all case change_impl_for(code, protocol, types, structs, false, []) do {:ok, ret} -> {:ok, {ret, docs}} other -> other end end defp change_impl_for([{:function, line, :__protocol__, 1, clauses}|t], protocol, types, structs, _, acc) do clauses = :lists.map(fn {:clause, l, [{:atom, _, :consolidated?}], [], [{:atom, _, _}]} -> {:clause, l, [{:atom, 0, :consolidated?}], [], [{:atom, 0, true}]} {:clause, _, _, _, _} = c -> c end, clauses) change_impl_for(t, protocol, types, structs, true, [{:function, line, :__protocol__, 1, clauses}|acc]) end defp change_impl_for([{:function, line, :impl_for, 1, _}|t], protocol, types, structs, is_protocol, acc) do fallback = if Any in types, do: load_impl(protocol, Any), else: nil clauses = for {guard, mod} <- builtin, mod in types, do: builtin_clause_for(mod, guard, protocol, line) clauses = [struct_clause_for(line)|clauses] ++ [fallback_clause_for(fallback, protocol, line)] change_impl_for(t, protocol, types, structs, is_protocol, [{:function, line, :impl_for, 1, clauses}|acc]) end defp change_impl_for([{:function, line, :struct_impl_for, 1, _}|t], protocol, types, structs, is_protocol, acc) do fallback = if Any in types, do: load_impl(protocol, Any), else: nil clauses = for struct <- structs, do: each_struct_clause_for(struct, protocol, line) clauses = clauses ++ [fallback_clause_for(fallback, protocol, line)] change_impl_for(t, protocol, types, structs, is_protocol, [{:function, line, :struct_impl_for, 1, clauses}|acc]) end defp change_impl_for([h|t], protocol, info, types, is_protocol, acc) do change_impl_for(t, protocol, info, types, is_protocol, [h|acc]) end defp change_impl_for([], protocol, _info, _types, is_protocol, acc) do if is_protocol do {:ok, {protocol, Enum.reverse(acc)}} else {:error, :not_a_protocol} end end defp builtin_clause_for(mod, guard, protocol, line) do {:clause, line, [{:var, line, :x}], [[{:call, line, {:remote, line, {:atom, line, :erlang}, {:atom, line, guard}}, [{:var, line, :x}], }]], [{:atom, line, load_impl(protocol, mod)}]} end defp struct_clause_for(line) do {:clause, line, [{:map, line, [ {:map_field_exact, line, {:atom, line, :__struct__}, {:var, line, :x}} ]}], [[{:call, line, {:remote, line, {:atom, line, :erlang}, {:atom, line, :is_atom}}, [{:var, line, :x}], }]], [{:call, line, {:atom, line, :struct_impl_for}, [{:var, line, :x}]}]} end defp each_struct_clause_for(other, protocol, line) do {:clause, line, [{:atom, line, other}], [], [{:atom, line, load_impl(protocol, other)}]} end defp fallback_clause_for(value, _protocol, line) do {:clause, line, [{:var, line, :_}], [], [{:atom, line, value}]} end defp load_impl(protocol, for) do Module.concat(protocol, for).__impl__(:target) end # Finally compile the module and emit its bytecode. defp compile({{protocol, code}, docs}) do opts = if Code.compiler_options[:debug_info], do: [:debug_info], else: [] {:ok, ^protocol, binary, _warnings} = :compile.forms(code, [:return|opts]) unless docs == :missing_chunk do binary = :elixir_module.add_beam_chunk(binary, @docs_chunk, docs) end {:ok, binary} end ## Definition callbacks @doc false def __protocol__(name, [do: block]) do quote do defmodule unquote(name) do # We don't allow function definition inside protocols import Kernel, except: [ defmacrop: 1, defmacrop: 2, defmacro: 1, defmacro: 2, defp: 1, defp: 2, def: 1, def: 2 ] # Import the new dsl that holds the new def import Protocol, only: [def: 1] # Compile with debug info for consolidation @compile :debug_info # Set up a clear slate to store defined functions @functions [] @fallback_to_any false # Invoke the user given block unquote(block) # Finalize expansion unquote(after_defprotocol) end end end defp after_defprotocol do quote bind_quoted: [builtin: builtin] do @spec impl_for(term) :: atom() | nil Kernel.def impl_for(data) # Define the implementation for structs. # # It simply delegates to struct_impl_for which is then # optimized during protocol consolidation. Kernel.def impl_for(%{__struct__: struct}) when :erlang.is_atom(struct) do struct_impl_for(struct) end # Define the implementation for builtins. :lists.foreach(fn {guard, mod} -> target = Module.concat(__MODULE__, mod) Kernel.def impl_for(data) when :erlang.unquote(guard)(data) do case impl_for?(unquote(target)) do true -> unquote(target).__impl__(:target) false -> any_impl_for end end end, builtin) @spec impl_for!(term) :: atom() | no_return() Kernel.def impl_for!(data) do impl_for(data) || raise(Protocol.UndefinedError, protocol: __MODULE__, value: data) end # Internal handler for Any if @fallback_to_any do Kernel.defp any_impl_for, do: __MODULE__.Any.__impl__(:target) else Kernel.defp any_impl_for, do: nil end # Internal handler for Structs Kernel.defp struct_impl_for(struct) do target = Module.concat(__MODULE__, struct) case impl_for?(target) do true -> target.__impl__(:target) false -> any_impl_for end end # Check if compilation is available internally Kernel.defp impl_for?(target) do Code.ensure_compiled?(target) and function_exported?(target, :__impl__, 1) end # Inline any and struct implementations @compile {:inline, any_impl_for: 0, struct_impl_for: 1, impl_for?: 1} unless Kernel.Typespec.defines_type?(__MODULE__, :t, 0) do @type t :: term end # Store information as an attribute so it # can be read without loading the module. Module.register_attribute(__MODULE__, :protocol, persist: true) @protocol [fallback_to_any: !!@fallback_to_any] @doc false @spec __protocol__(:module) :: __MODULE__ @spec __protocol__(:functions) :: unquote(Protocol.__functions_spec__(@functions)) @spec __protocol__(:consolidated?) :: boolean Kernel.def __protocol__(:module), do: __MODULE__ Kernel.def __protocol__(:functions), do: unquote(:lists.sort(@functions)) Kernel.def __protocol__(:consolidated?), do: false end end @doc false def __functions_spec__([]), do: [] def __functions_spec__([h|t]), do: [:lists.foldl(&{:|, [], [&1, &2]}, h, t), quote(do: ...)] @doc false def __impl__(protocol, opts) do do_defimpl(protocol, :lists.keysort(1, opts)) end defp do_defimpl(protocol, [do: block, for: for]) when is_list(for) do for f <- for, do: do_defimpl(protocol, [do: block, for: f]) end defp do_defimpl(protocol, [do: block, for: for]) do # Unquote the implementation just later # when all variables will already be injected # into the module body. __impl__ = quote unquote: false do @doc false @spec __impl__(:for) :: unquote(for) @spec __impl__(:target) :: __MODULE__ @spec __impl__(:protocol) :: unquote(protocol) def __impl__(:for), do: unquote(for) def __impl__(:target), do: __MODULE__ def __impl__(:protocol), do: unquote(protocol) end quote do protocol = unquote(protocol) for = unquote(for) name = Module.concat(protocol, for) # TODO: Emit warnings once we reimplement Access before 1.1 # if protocol == Access do # :elixir_errors.warn __ENV__.line, __ENV__.file, # "implementation of the Access protocol is deprecated. For customization of " <> # "the dict[key] syntax, please implement the Dict behaviour instead" # end Protocol.assert_protocol!(protocol) defmodule name do @behaviour protocol @protocol protocol @for for unquote(block) Module.register_attribute(__MODULE__, :impl, persist: true) @impl [protocol: @protocol, for: @for] unquote(__impl__) end end end @doc false def __derive__(derives, for, %Macro.Env{} = env) when is_atom(for) do struct = if for == env.module do Module.get_attribute(for, :struct) || raise "struct is not defined for #{inspect for}" else for.__struct__ end :lists.foreach(fn proto when is_atom(proto) -> derive(proto, for, struct, [], env) {proto, opts} when is_atom(proto) -> derive(proto, for, struct, opts, env) end, :lists.flatten(derives)) :ok end defp derive(protocol, for, struct, opts, env) do extra = ", cannot derive #{inspect protocol} for #{inspect for}" assert_protocol!(protocol, extra) assert_impl!(protocol, Any, extra) # Clean up variables from eval context env = %{env | vars: [], export_vars: nil} args = [for, struct, opts] impl = Module.concat(protocol, Any) :elixir_module.expand_callback(env.line, impl, :__deriving__, args, env, fn mod, fun, args -> if function_exported?(mod, fun, length(args)) do apply(mod, fun, args) else Module.create(Module.concat(protocol, for), quote do Module.register_attribute(__MODULE__, :impl, persist: true) @impl [protocol: unquote(protocol), for: unquote(for)] @doc false @spec __impl__(:target) :: unquote(impl) @spec __impl__(:protocol) :: unquote(protocol) @spec __impl__(:for) :: unquote(for) def __impl__(:target), do: unquote(impl) def __impl__(:protocol), do: unquote(protocol) def __impl__(:for), do: unquote(for) end, Macro.Env.location(env)) end end) end @doc false def __spec__?(module, name, arity) do signature = {name, arity} specs = Module.get_attribute(module, :spec) found = :lists.map(fn {:spec, expr, caller} -> if Kernel.Typespec.spec_to_signature(expr) == signature do Kernel.Typespec.define_spec(:callback, expr, caller) true end end, specs) :lists.any(& &1 == true, found) end ## Helpers defp builtin do [is_tuple: Tuple, is_atom: Atom, is_list: List, is_map: Map, is_bitstring: BitString, is_integer: Integer, is_float: Float, is_function: Function, is_pid: PID, is_port: Port, is_reference: Reference] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/range.ex000066400000000000000000000050151254730255300213600ustar00rootroot00000000000000defmodule Range do @moduledoc """ Defines a Range. A Range is represented internally as a struct. However, the most common form of creating and matching on ranges is via the `../2` macro, auto-imported from Kernel: iex> range = 1..3 1..3 iex> first .. last = range iex> first 1 iex> last 3 """ defstruct first: nil, last: nil @type t :: %Range{} @type t(first, last) :: %Range{first: first, last: last} @doc """ Creates a new range. """ def new(first, last) do %Range{first: first, last: last} end @doc """ Returns `true` if the given argument is a range. ## Examples iex> Range.range?(1..3) true iex> Range.range?(0) false """ def range?(%Range{}), do: true def range?(_), do: false end defprotocol Range.Iterator do @moduledoc """ A protocol used for iterating range elements. """ @doc """ Returns the function that calculates the next item. """ def next(first, range) @doc """ Counts how many items are in the range. """ def count(first, range) end defimpl Enumerable, for: Range do def reduce(first .. last = range, acc, fun) do reduce(first, last, acc, fun, Range.Iterator.next(first, range), last >= first) end defp reduce(_x, _y, {:halt, acc}, _fun, _next, _up) do {:halted, acc} end defp reduce(x, y, {:suspend, acc}, fun, next, up) do {:suspended, acc, &reduce(x, y, &1, fun, next, up)} end defp reduce(x, y, {:cont, acc}, fun, next, true) when x <= y do reduce(next.(x), y, fun.(x, acc), fun, next, true) end defp reduce(x, y, {:cont, acc}, fun, next, false) when x >= y do reduce(next.(x), y, fun.(x, acc), fun, next, false) end defp reduce(_, _, {:cont, acc}, _fun, _next, _up) do {:done, acc} end def member?(first .. last, value) do if first <= last do {:ok, first <= value and value <= last} else {:ok, last <= value and value <= first} end end def count(first .. _ = range) do {:ok, Range.Iterator.count(first, range)} end end defimpl Range.Iterator, for: Integer do def next(first, _ .. last) when is_integer(last) do if last >= first do &(&1 + 1) else &(&1 - 1) end end def count(first, _ .. last) when is_integer(last) do if last >= first do last - first + 1 else first - last + 1 end end end defimpl Inspect, for: Range do import Inspect.Algebra def inspect(first .. last, opts) do concat [to_doc(first, opts), "..", to_doc(last, opts)] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/record.ex000066400000000000000000000263771254730255300215600ustar00rootroot00000000000000defmodule Record do @moduledoc """ Module to work, define and import records. Records are simply tuples where the first element is an atom: iex> Record.is_record {User, "john", 27} true This module provides conveniences for working with records at compilation time, where compile-time field names are used to manipulate the tuples, providing fast operations on top of the tuples compact structure. In Elixir, records are used mostly in two situations: 1. to work with short, internal data 2. to interface with Erlang records The macros `defrecord/3` and `defrecordp/3` can be used to create records while `extract/2` can be used to extract records from Erlang files. ## Types Types can be defined for tuples with the `record/2` macro (only available in typespecs). Like with the generated record macros it will expand to a tuple. defmodule MyModule do require Record Record.defrecord :user, name: "john", age: 25 @type user :: record(:user, name: String.t, age: integer) # expands to: `@type user :: {:user, String.t, integer}` end """ @doc """ Extracts record information from an Erlang file. Returns a quoted expression containing the fields as a list of tuples. It expects the record name to be an atom and the library path to be a string at expansion time. ## Examples iex> Record.extract(:file_info, from_lib: "kernel/include/file.hrl") [size: :undefined, type: :undefined, access: :undefined, atime: :undefined, mtime: :undefined, ctime: :undefined, mode: :undefined, links: :undefined, major_device: :undefined, minor_device: :undefined, inode: :undefined, uid: :undefined, gid: :undefined] """ def extract(name, opts) when is_atom(name) and is_list(opts) do Record.Extractor.extract(name, opts) end @doc """ Extracts all records information from an Erlang file. Returns a keyword list containing extracted record names as keys, and lists of tuples describing the fields as values. It expects a named argument :from or :from_lib, which correspond to *include* or *include_lib* attribute from Erlang modules, respectively. """ def extract_all(opts) when is_list(opts) do Record.Extractor.extract_all(opts) end @doc """ Checks if the given `data` is a record of `kind`. This is implemented as a macro so it can be used in guard clauses. ## Examples iex> record = {User, "john", 27} iex> Record.is_record(record, User) true """ defmacro is_record(data, kind) do case Macro.Env.in_guard?(__CALLER__) do true -> quote do is_tuple(unquote(data)) and tuple_size(unquote(data)) > 0 and :erlang.element(1, unquote(data)) == unquote(kind) end false -> quote do result = unquote(data) is_tuple(result) and tuple_size(result) > 0 and :erlang.element(1, result) == unquote(kind) end end end @doc """ Checks if the given `data` is a record. This is implemented as a macro so it can be used in guard clauses. ## Examples iex> record = {User, "john", 27} iex> Record.is_record(record) true iex> tuple = {} iex> Record.is_record(tuple) false """ defmacro is_record(data) do case Macro.Env.in_guard?(__CALLER__) do true -> quote do is_tuple(unquote(data)) and tuple_size(unquote(data)) > 0 and is_atom(:erlang.element(1, unquote(data))) end false -> quote do result = unquote(data) is_tuple(result) and tuple_size(result) > 0 and is_atom(:erlang.element(1, result)) end end end @doc """ Defines a set of macros to create and access a record. The macros are going to have `name`, a tag (which defaults) to the name if none is given, and a set of fields given by `kv`. ## Examples defmodule User do require Record Record.defrecord :user, [name: "meg", age: "25"] end In the example above, a set of macros named `user` but with different arities will be defined to manipulate the underlying record: # To create records record = user() #=> {:user, "meg", 25} record = user(age: 26) #=> {:user, "meg", 26} # To get a field from the record user(record, :name) #=> "meg" # To update the record user(record, age: 26) #=> {:user, "meg", 26} # Convert a record to a keyword list user(record) #=> [name: "meg", age: 26] The generated macros can also be used in order to pattern match on records and to bind variables during the match: record = user() #=> {:user, "meg", 25} user(name: name) = record name #=> "meg" By default, Elixir uses the record name as the first element of the tuple (the tag). But it can be changed to something else: defmodule User do require Record Record.defrecord :user, User, name: nil end require User User.user() #=> {User, nil} ## Defining extracted records with anonymous functions If a record defines an anonymous function, an ArgumentError will occur if you attempt to create a record with it. This can occur unintentionally when defining a record after extracting it from an Erlang library that uses anonymous functions for defaults. Record.defrecord :my_rec, Record.extract(...) #=> ** (ArgumentError) invalid value for record field fun_field, cannot escape #Function<12.90072148/2 in :erl_eval.expr/5>. To work around this error, redefine the field with your own &M.f/a function, like so: defmodule MyRec do require Record Record.defrecord :my_rec, Record.extract(...) |> Keyword.merge(fun_field: &__MODULE__.foo/2) def foo(bar, baz), do: IO.inspect({bar, baz}) end """ defmacro defrecord(name, tag \\ nil, kv) do quote bind_quoted: [name: name, tag: tag, kv: kv] do tag = tag || name fields = Record.__fields__(:defrecord, kv) defmacro(unquote(name)(args \\ [])) do Record.__access__(unquote(tag), unquote(fields), args, __CALLER__) end defmacro(unquote(name)(record, args)) do Record.__access__(unquote(tag), unquote(fields), record, args, __CALLER__) end end end @doc """ Same as `defrecord/3` but generates private macros. """ defmacro defrecordp(name, tag \\ nil, kv) do quote bind_quoted: [name: name, tag: tag, kv: kv] do tag = tag || name fields = Record.__fields__(:defrecordp, kv) defmacrop(unquote(name)(args \\ [])) do Record.__access__(unquote(tag), unquote(fields), args, __CALLER__) end defmacrop(unquote(name)(record, args)) do Record.__access__(unquote(tag), unquote(fields), record, args, __CALLER__) end end end # Normalizes of record fields to have default values. @doc false def __fields__(type, fields) do :lists.map(fn {key, val} when is_atom(key) -> try do Macro.escape(val) rescue e in [ArgumentError] -> raise ArgumentError, "invalid value for record field #{key}, " <> Exception.message(e) else val -> {key, val} end key when is_atom(key) -> {key, nil} other -> raise ArgumentError, "#{type} fields must be atoms, got: #{inspect other}" end, fields) end # Callback invoked from record/0 and record/1 macros. @doc false def __access__(atom, fields, args, caller) do cond do is_atom(args) -> index(atom, fields, args) Keyword.keyword?(args) -> create(atom, fields, args, caller) true -> case Macro.expand(args, caller) do {:{}, _, [^atom|list]} when length(list) == length(fields) -> record = List.to_tuple([atom|list]) Macro.escape(Record.__keyword__(atom, fields, record)) {^atom, arg} when length(fields) == 1 -> Macro.escape(Record.__keyword__(atom, fields, {atom, arg})) _ -> quote do: Record.__keyword__(unquote(atom), unquote(fields), unquote(args)) end end end # Callback invoked from the record/2 macro. @doc false def __access__(atom, fields, record, args, caller) do cond do is_atom(args) -> get(atom, fields, record, args) Keyword.keyword?(args) -> update(atom, fields, record, args, caller) true -> msg = "expected arguments to be a compile time atom or keywords, got: #{Macro.to_string args}" raise ArgumentError, msg end end # Gets the index of field. defp index(atom, fields, field) do if index = find_index(fields, field, 0) do index - 1 # Convert to Elixir index else raise ArgumentError, "record #{inspect atom} does not have the key: #{inspect field}" end end # Creates a new record with the given default fields and keyword values. defp create(atom, fields, keyword, caller) do in_match = Macro.Env.in_match?(caller) {match, remaining} = Enum.map_reduce(fields, keyword, fn({field, default}, each_keyword) -> new_fields = case Keyword.has_key?(each_keyword, field) do true -> Keyword.get(each_keyword, field) false -> case in_match do true -> {:_, [], nil} false -> Macro.escape(default) end end {new_fields, Keyword.delete(each_keyword, field)} end) case remaining do [] -> {:{}, [], [atom|match]} _ -> keys = for {key, _} <- remaining, do: key raise ArgumentError, "record #{inspect atom} does not have the key: #{inspect hd(keys)}" end end # Updates a record given by var with the given keyword. defp update(atom, fields, var, keyword, caller) do if Macro.Env.in_match?(caller) do raise ArgumentError, "cannot invoke update style macro inside match" end Enum.reduce keyword, var, fn({key, value}, acc) -> index = find_index(fields, key, 0) if index do quote do :erlang.setelement(unquote(index), unquote(acc), unquote(value)) end else raise ArgumentError, "record #{inspect atom} does not have the key: #{inspect key}" end end end # Gets a record key from the given var. defp get(atom, fields, var, key) do index = find_index(fields, key, 0) if index do quote do :erlang.element(unquote(index), unquote(var)) end else raise ArgumentError, "record #{inspect atom} does not have the key: #{inspect key}" end end defp find_index([{k, _}|_], k, i), do: i + 2 defp find_index([{_, _}|t], k, i), do: find_index(t, k, i + 1) defp find_index([], _k, _i), do: nil # Returns a keyword list of the record @doc false def __keyword__(atom, fields, record) do if is_record(record, atom) do [_tag|values] = Tuple.to_list(record) join_keyword(fields, values, []) else msg = "expected argument to be a literal atom, literal keyword or a #{inspect atom} record, got runtime: #{inspect record}" raise ArgumentError, msg end end defp join_keyword([{field, _default}|fields], [value|values], acc), do: join_keyword(fields, values, [{field, value}| acc]) defp join_keyword([], [], acc), do: :lists.reverse(acc) end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/record/000077500000000000000000000000001254730255300212035ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/record/extractor.ex000066400000000000000000000072361254730255300235640ustar00rootroot00000000000000defmodule Record.Extractor do @moduledoc false # Retrieve a record definition from an Erlang file using # the same lookup as the *include* attribute from Erlang modules. def extract(name, from: file) when is_binary(file) do extract_record(name, from_file(file)) end # Retrieve a record definition from an Erlang file using # the same lookup as the *include_lib* attribute from Erlang modules. def extract(name, from_lib: file) when is_binary(file) do extract_record(name, from_lib_file(file)) end # Retrieve all records definitions from an Erlang file using # the same lookup as the *include* attribute from Erlang modules. def extract_all(from: file) when is_binary(file) do extract_all_records(from_file(file)) end # Retrieve all records definitions from an Erlang file using # the same lookup as the *include_lib* attribute from Erlang modules. def extract_all(from_lib: file) when is_binary(file) do extract_all_records(from_lib_file(file)) end # Find file using the same lookup as the *include* attribute from Erlang modules. defp from_file(file) do file = String.to_char_list(file) case :code.where_is_file(file) do :non_existing -> file realfile -> realfile end end # Find file using the same lookup as the *include_lib* attribute from Erlang modules. defp from_lib_file(file) do [app|path] = :filename.split(String.to_char_list(file)) case :code.lib_dir(List.to_atom(app)) do {:error, _} -> raise ArgumentError, "lib file #{file} could not be found" libpath -> :filename.join([libpath|path]) end end # Retrieve the record with the given name from the given file defp extract_record(name, file) do form = read_file(file) records = extract_records(form) if record = List.keyfind(records, name, 0) do parse_record(record, form) else raise ArgumentError, "no record #{name} found at #{file}" end end # Retrieve all records from the given file defp extract_all_records(file) do form = read_file(file) records = extract_records(form) for rec = {name, _fields} <- records, do: {name, parse_record(rec, form)} end # Parse the given file and extract all existent records. defp extract_records(form) do for {:attribute, _, :record, record} <- form, do: record end # Read a file and return its abstract syntax form that also # includes record but with macros and other attributes expanded, # such as `-include(...)` and `-include_lib(...)`. This is done # by using Erlang's epp. defp read_file(file) do case :epp.parse_file(file, []) do {:ok, form} -> form other -> raise "error parsing file #{file}, got: #{inspect(other)}" end end # Parse a tuple with name and fields and returns a # list of tuples where the first element is the field # and the second is its default value. defp parse_record({_name, fields}, form) do cons = List.foldr fields, {nil, 0}, fn f, acc -> {:cons, 0, parse_field(f), acc} end eval_record(cons, form) end defp parse_field({:typed_record_field, record_field, _type}) do parse_field(record_field) end defp parse_field({:record_field, _, key}) do {:tuple, 0, [key, {:atom, 0, :undefined}]} end defp parse_field({:record_field, _, key, value}) do {:tuple, 0, [key, value]} end defp eval_record(cons, form) do form = form ++ [{:function, 0, :hello, 0, [ {:clause, 0, [], [], [cons]}]}] {:function, 0, :hello, 0, [ {:clause, 0, [], [], [record_ast]}]} = :erl_expand_records.module(form, []) |> List.last {:value, record, _} = :erl_eval.expr(record_ast, []) record end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/regex.ex000066400000000000000000000446621254730255300214110ustar00rootroot00000000000000defmodule Regex do @moduledoc ~S""" Regular expressions for Elixir built on top of Erlang's `re` module. As the `re` module, Regex is based on PCRE (Perl Compatible Regular Expressions). More information can be found in the [`re` documentation](http://www.erlang.org/doc/man/re.html). Regular expressions in Elixir can be created using `Regex.compile!/2` or using the special form with [`~r`](Kernel.html#sigil_r/2): # A simple regular expressions that matches foo anywhere in the string ~r/foo/ # A regular expression with case insensitive and unicode options ~r/foo/iu A Regex is represented internally as the `Regex` struct. Therefore, `%Regex{}` can be used whenever there is a need to match on them. ## Modifiers The modifiers available when creating a Regex are: * `unicode` (u) - enables unicode specific patterns like `\p` and changes modifiers like `\w`, `\W`, `\s` and friends to also match on unicode. It expects valid unicode strings to be given on match * `caseless` (i) - add case insensitivity * `dotall` (s) - causes dot to match newlines and also set newline to anycrlf; the new line setting can be overridden by setting `(*CR)` or `(*LF)` or `(*CRLF)` or `(*ANY)` according to re documentation * `multiline` (m) - causes `^` and `$` to mark the beginning and end of each line; use `\A` and `\z` to match the end or beginning of the string * `extended` (x) - whitespace characters are ignored except when escaped and allow `#` to delimit comments * `firstline` (f) - forces the unanchored pattern to match before or at the first newline, though the matched text may continue over the newline * `ungreedy` (U) - inverts the "greediness" of the regexp (the previous `r` option is deprecated in favor of `U`) The options not available are: * `anchored` - not available, use `^` or `\A` instead * `dollar_endonly` - not available, use `\z` instead * `no_auto_capture` - not available, use `?:` instead * `newline` - not available, use `(*CR)` or `(*LF)` or `(*CRLF)` or `(*ANYCRLF)` or `(*ANY)` at the beginning of the regexp according to the re documentation ## Captures Many functions in this module allows what to capture in a regex match via the `:capture` option. The supported values are: * `:all` - all captured subpatterns including the complete matching string (this is the default) * `:first` - only the first captured subpattern, which is always the complete matching part of the string; all explicitly captured subpatterns are discarded * `:all_but_first`- all but the first matching subpattern, i.e. all explicitly captured subpatterns, but not the complete matching part of the string * `:none` - do not return matching subpatterns at all * `:all_names` - captures all names in the Regex * `list(binary)` - a list of named captures to capture """ defstruct re_pattern: nil, source: "", opts: "" @type t :: %__MODULE__{re_pattern: term, source: binary, opts: binary} defmodule CompileError do defexception message: "regex could not be compiled" end @doc """ Compiles the regular expression. The given options can either be a binary with the characters representing the same regex options given to the `~r` sigil, or a list of options, as expected by the [Erlang `re` docs](http://www.erlang.org/doc/man/re.html). It returns `{:ok, regex}` in case of success, `{:error, reason}` otherwise. ## Examples iex> Regex.compile("foo") {:ok, ~r"foo"} iex> Regex.compile("*foo") {:error, {'nothing to repeat', 0}} """ @spec compile(binary, binary | [term]) :: {:ok, t} | {:error, any} def compile(source, options \\ "") def compile(source, options) when is_binary(options) do case translate_options(options, []) do {:error, rest} -> {:error, {:invalid_option, rest}} translated_options -> compile(source, translated_options, options) end end def compile(source, options) when is_list(options) do compile(source, options, "") end defp compile(source, opts, doc_opts) when is_binary(source) do case :re.compile(source, opts) do {:ok, re_pattern} -> {:ok, %Regex{re_pattern: re_pattern, source: source, opts: doc_opts}} error -> error end end @doc """ Compiles the regular expression according to the given options. Fails with `Regex.CompileError` if the regex cannot be compiled. """ @spec compile(binary, binary | [term]) :: t def compile!(source, options \\ "") do case compile(source, options) do {:ok, regex} -> regex {:error, {reason, at}} -> raise Regex.CompileError, message: "#{reason} at position #{at}" end end @doc """ Returns a boolean indicating whether there was a match or not. ## Examples iex> Regex.match?(~r/foo/, "foo") true iex> Regex.match?(~r/foo/, "bar") false """ @spec match?(t, String.t) :: boolean def match?(%Regex{re_pattern: compiled}, string) when is_binary(string) do :re.run(string, compiled, [{:capture, :none}]) == :match end @doc """ Returns `true` if the given argument is a regex. ## Examples iex> Regex.regex?(~r/foo/) true iex> Regex.regex?(0) false """ @spec regex?(t) :: true @spec regex?(any) :: false def regex?(%Regex{}), do: true def regex?(_), do: false @doc """ Runs the regular expression against the given string until the first match. It returns a list with all captures or `nil` if no match occurred. ## Options * `:return` - set to `:index` to return indexes. Defaults to `:binary`. * `:capture` - what to capture in the result. Check the moduledoc for `Regex` to see the possible capture values. ## Examples iex> Regex.run(~r/c(d)/, "abcd") ["cd", "d"] iex> Regex.run(~r/e/, "abcd") nil iex> Regex.run(~r/c(d)/, "abcd", return: :index) [{2, 2}, {3, 1}] """ @spec run(t, binary, [term]) :: nil | [binary] | [{integer, integer}] def run(regex, string, options \\ []) def run(%Regex{re_pattern: compiled}, string, options) when is_binary(string) do return = Keyword.get(options, :return, :binary) captures = Keyword.get(options, :capture, :all) case :re.run(string, compiled, [{:capture, captures, return}]) do :nomatch -> nil :match -> [] {:match, results} -> results end end @doc """ Returns the given captures as a map or `nil` if no captures are found. The option `:return` can be set to `:index` to get indexes back. ## Examples iex> Regex.named_captures(~r/c(?d)/, "abcd") %{"foo" => "d"} iex> Regex.named_captures(~r/a(?b)c(?d)/, "abcd") %{"bar" => "d", "foo" => "b"} iex> Regex.named_captures(~r/a(?b)c(?d)/, "efgh") nil """ @spec named_captures(t, String.t, [term]) :: map | nil def named_captures(regex, string, options \\ []) when is_binary(string) do names = names(regex) options = Keyword.put(options, :capture, names) results = run(regex, string, options) if results, do: Enum.zip(names, results) |> Enum.into(%{}) end @doc """ Returns the underlying `re_pattern` in the regular expression. """ @spec re_pattern(t) :: term def re_pattern(%Regex{re_pattern: compiled}) do compiled end @doc """ Returns the regex source as a binary. ## Examples iex> Regex.source(~r(foo)) "foo" """ @spec source(t) :: String.t def source(%Regex{source: source}) do source end @doc """ Returns the regex options as a string. ## Examples iex> Regex.opts(~r(foo)m) "m" """ @spec opts(t) :: String.t def opts(%Regex{opts: opts}) do opts end @doc """ Returns a list of names in the regex. ## Examples iex> Regex.names(~r/(?bar)/) ["foo"] """ @spec names(t) :: [String.t] def names(%Regex{re_pattern: re_pattern}) do {:namelist, names} = :re.inspect(re_pattern, :namelist) names end @doc """ Same as `run/3`, but scans the target several times collecting all matches of the regular expression. A list of lists is returned, where each entry in the primary list represents a match and each entry in the secondary list represents the captured contents. ## Options * `:return` - set to `:index` to return indexes. Defaults to `:binary`. * `:capture` - what to capture in the result. Check the moduledoc for `Regex` to see the possible capture values. ## Examples iex> Regex.scan(~r/c(d|e)/, "abcd abce") [["cd", "d"], ["ce", "e"]] iex> Regex.scan(~r/c(?:d|e)/, "abcd abce") [["cd"], ["ce"]] iex> Regex.scan(~r/e/, "abcd") [] """ @spec scan(t, String.t, [term]) :: [[String.t]] def scan(regex, string, options \\ []) def scan(%Regex{re_pattern: compiled}, string, options) when is_binary(string) do return = Keyword.get(options, :return, :binary) captures = Keyword.get(options, :capture, :all) options = [{:capture, captures, return}, :global] case :re.run(string, compiled, options) do :match -> [] :nomatch -> [] {:match, results} -> results end end @doc """ Splits the given target based on the given pattern and in the given number of parts. ## Options * `:parts` - when specified, splits the string into the given number of parts. If not specified, `:parts` defaults to `:infinity`, which will split the string into the maximum number of parts possible based on the given pattern. * `:trim` - when `true`, removes empty strings (`""`) from the result. * `:on` - specifies which captures to split the string on, and in what order. Defaults to `:first` which means captures inside the regex do not affect the splitting process. ## Examples iex> Regex.split(~r/-/, "a-b-c") ["a", "b", "c"] iex> Regex.split(~r/-/, "a-b-c", [parts: 2]) ["a", "b-c"] iex> Regex.split(~r/-/, "abc") ["abc"] iex> Regex.split(~r//, "abc") ["a", "b", "c", ""] iex> Regex.split(~r/a(?b)c/, "abc") ["", ""] iex> Regex.split(~r/a(?b)c/, "abc", on: [:second]) ["a", "c"] """ @spec split(t, String.t, [term]) :: [String.t] def split(regex, string, options \\ []) def split(%Regex{}, "", opts) do if Keyword.get(opts, :trim, false) do [] else [""] end end def split(%Regex{re_pattern: compiled}, string, opts) when is_binary(string) do on = Keyword.get(opts, :on, :first) case :re.run(string, compiled, [:global, capture: on]) do {:match, matches} -> do_split(matches, string, 0, parts_to_index(Keyword.get(opts, :parts, :infinity)), Keyword.get(opts, :trim, false)) :match -> [string] :nomatch -> [string] end end defp parts_to_index(:infinity), do: 0 defp parts_to_index(n) when is_integer(n) and n > 0, do: n defp do_split(_, string, offset, _counter, true) when byte_size(string) <= offset, do: [] defp do_split(_, string, offset, 1, _trim), do: [binary_part(string, offset, byte_size(string) - offset)] defp do_split([], string, offset, _counter, _trim), do: [binary_part(string, offset, byte_size(string) - offset)] defp do_split([[{pos, _}|h]|t], string, offset, counter, trim) when pos - offset < 0, do: do_split([h|t], string, offset, counter, trim) defp do_split([[]|t], string, offset, counter, trim), do: do_split(t, string, offset, counter, trim) defp do_split([[{pos, length}|h]|t], string, offset, counter, trim) do new_offset = pos + length keep = pos - offset if keep == 0 and (length == 0 or trim) do do_split([h|t], string, new_offset, counter, trim) else <<_::binary-size(offset), part::binary-size(keep), _::binary>> = string [part|do_split([h|t], string, new_offset, counter - 1, trim)] end end @doc ~S""" Receives a regex, a binary and a replacement, returns a new binary where the all matches are replaced by replacement. The replacement can be either a string or a function. The string is used as a replacement for every match and it allows specific captures to be accessed via `\\N` or `\g{N}`, where `N` is the capture. In case `\\0` is used, the whole match is inserted. When the replacement is a function, the function may have arity N where each argument maps to a capture, with the first argument being the whole match. If the function expects more arguments than captures found, the remaining arguments will receive `""`. ## Options * `:global` - when `false`, replaces only the first occurrence (defaults to `true`) ## Examples iex> Regex.replace(~r/d/, "abc", "d") "abc" iex> Regex.replace(~r/b/, "abc", "d") "adc" iex> Regex.replace(~r/b/, "abc", "[\\0]") "a[b]c" iex> Regex.replace(~r/a(b|d)c/, "abcadc", "[\\1]") "[b][d]" iex> Regex.replace(~r/a(b|d)c/, "abcadc", fn _, x -> "[#{x}]" end) "[b][d]" iex> Regex.replace(~r/a/, "abcadc", "A", global: false) "Abcadc" """ @spec replace(t, String.t, String.t | (... -> String.t), [term]) :: String.t def replace(regex, string, replacement, options \\ []) def replace(regex, string, replacement, options) when is_binary(replacement) do do_replace(regex, string, precompile_replacement(replacement), options) end def replace(regex, string, replacement, options) when is_function(replacement) do {:arity, arity} = :erlang.fun_info(replacement, :arity) do_replace(regex, string, {replacement, arity}, options) end defp do_replace(%Regex{re_pattern: compiled}, string, replacement, options) do opts = if Keyword.get(options, :global) != false, do: [:global], else: [] opts = [{:capture, :all, :index}|opts] case :re.run(string, compiled, opts) do :nomatch -> string {:match, [mlist|t]} when is_list(mlist) -> apply_list(string, replacement, [mlist|t]) |> IO.iodata_to_binary {:match, slist} -> apply_list(string, replacement, [slist]) |> IO.iodata_to_binary end end defp precompile_replacement(""), do: [] defp precompile_replacement(<>) when byte_size(rest) > 0 do {ns, <>} = pick_int(rest) [List.to_integer(ns) | precompile_replacement(rest)] end defp precompile_replacement(<>) do [<> | precompile_replacement(rest)] end defp precompile_replacement(<>) when x in ?0..?9 do {ns, rest} = pick_int(rest) [List.to_integer([x|ns]) | precompile_replacement(rest)] end defp precompile_replacement(<>) do case precompile_replacement(rest) do [head | t] when is_binary(head) -> [<> | t] other -> [<> | other] end end defp pick_int(<>) when x in ?0..?9 do {found, rest} = pick_int(rest) {[x|found], rest} end defp pick_int(bin) do {[], bin} end defp apply_list(string, replacement, list) do apply_list(string, string, 0, replacement, list) end defp apply_list(_, "", _, _, []) do [] end defp apply_list(_, string, _, _, []) do string end defp apply_list(whole, string, pos, replacement, [[{mpos, _} | _] | _] = list) when mpos > pos do length = mpos - pos <> = string [untouched | apply_list(whole, rest, mpos, replacement, list)] end defp apply_list(whole, string, pos, replacement, [[{pos, length} | _] = head | tail]) do <<_ :: size(length)-binary, rest :: binary>> = string new_data = apply_replace(whole, replacement, head) [new_data | apply_list(whole, rest, pos + length, replacement, tail)] end defp apply_replace(string, {fun, arity}, indexes) do apply(fun, get_indexes(string, indexes, arity)) end defp apply_replace(_, [bin], _) when is_binary(bin) do bin end defp apply_replace(string, repl, indexes) do indexes = List.to_tuple(indexes) for part <- repl do cond do is_binary(part) -> part part >= tuple_size(indexes) -> "" true -> get_index(string, elem(indexes, part)) end end end defp get_index(_string, {pos, _len}) when pos < 0 do "" end defp get_index(string, {pos, len}) do <<_ :: size(pos)-binary, res :: size(len)-binary, _ :: binary>> = string res end defp get_indexes(_string, _, 0) do [] end defp get_indexes(string, [], arity) do [""|get_indexes(string, [], arity - 1)] end defp get_indexes(string, [h|t], arity) do [get_index(string, h)|get_indexes(string, t, arity - 1)] end {:ok, pattern} = :re.compile(~S"[.^$*+?()[{\\\|\s#]", [:unicode]) @escape_pattern pattern @doc ~S""" Escapes a string to be literally matched in a regex. ## Examples iex> Regex.escape(".") "\\." iex> Regex.escape("\\what if") "\\\\what\\ if" """ @spec escape(String.t) :: String.t def escape(string) when is_binary(string) do :re.replace(string, @escape_pattern, "\\\\&", [:global, {:return, :binary}]) end # Helpers @doc false # Unescape map function used by Macro.unescape_string. def unescape_map(?f), do: ?\f def unescape_map(?n), do: ?\n def unescape_map(?r), do: ?\r def unescape_map(?t), do: ?\t def unescape_map(?v), do: ?\v def unescape_map(?a), do: ?\a def unescape_map(_), do: false # Private Helpers defp translate_options(<>, acc), do: translate_options(t, [:unicode, :ucp|acc]) defp translate_options(<>, acc), do: translate_options(t, [:caseless|acc]) defp translate_options(<>, acc), do: translate_options(t, [:extended|acc]) defp translate_options(<>, acc), do: translate_options(t, [:firstline|acc]) defp translate_options(<>, acc), do: translate_options(t, [:ungreedy|acc]) defp translate_options(<>, acc), do: translate_options(t, [:dotall, {:newline, :anycrlf}|acc]) defp translate_options(<>, acc), do: translate_options(t, [:multiline|acc]) # TODO: Deprecate by 1.2 # TODO: Remove by 2.0 defp translate_options(<>, acc), do: translate_options(t, [:ungreedy|acc]) defp translate_options(<<>>, acc), do: acc defp translate_options(rest, _acc), do: {:error, rest} end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/set.ex000066400000000000000000000205371254730255300210650ustar00rootroot00000000000000defmodule Set do @moduledoc ~S""" This module specifies the `Set` behaviour expected to be implemented by different representations of sets. It also provides functions that redirect to the underlying implementation, allowing a developer to work with different `Set` implementations using a common API. To create a new set, use the `new` function which each set implementation defines: HashSet.new #=> creates an empty HashSet In the examples below, `set_impl` means a specific `Set` implementation, for example `HashSet`. ## Protocols Sets are required to implement both the `Enumerable` and `Collectable` protocols. ## Matching Sets are required to implement all equality checks using the match (`===`) operator. """ use Behaviour @type value :: any @type values :: [ value ] @type t :: map defcallback new :: t defcallback delete(t, value) :: t defcallback difference(t, t) :: t defcallback disjoint?(t, t) :: boolean defcallback equal?(t, t) :: boolean defcallback intersection(t, t) :: t defcallback member?(t, value) :: boolean defcallback put(t, value) :: t defcallback size(t) :: non_neg_integer defcallback subset?(t, t) :: boolean defcallback to_list(t) :: list() defcallback union(t, t) :: t defmacrop target(set) do quote do case unquote(set) do %{__struct__: x} when is_atom(x) -> x x -> unsupported_set(x) end end end @doc """ Deletes `value` from `set`. Returns a new set which is a copy of `set` but without `value`. ## Examples iex> s = Enum.into([1, 2, 3], set_impl.new) iex> Set.delete(s, 4) |> Enum.sort [1, 2, 3] iex> s = Enum.into([1, 2, 3], set_impl.new) iex> Set.delete(s, 2) |> Enum.sort [1, 3] """ @spec delete(t, value) :: t def delete(set, value) do target(set).delete(set, value) end @doc """ Returns a set that is `set1` without the members of `set2`. Note that this function is polymorphic as it calculates the difference for sets of the same type as well as of sets of different types. Each set implementation also provides a `difference` function which only works with sets of that type. ## Examples iex> Set.difference(Enum.into([1, 2], set_impl.new), Enum.into([2, 3, 4], set_impl.new)) |> Enum.sort [1] """ @spec difference(t, t) :: t def difference(set1, set2) do target1 = target(set1) target2 = target(set2) if target1 == target2 do target1.difference(set1, set2) else target2.reduce(set2, {:cont, set1}, fn v, acc -> {:cont, target1.delete(acc, v)} end) |> elem(1) end end @doc """ Checks if `set1` and `set2` have no members in common. Note that this function is polymorphic as it checks for disjoint sets of any type. Each set implementation also provides a `disjoint?` function, but that function can only work with sets of the same type. ## Examples iex> Set.disjoint?(Enum.into([1, 2], set_impl.new), Enum.into([3, 4], set_impl.new)) true iex> Set.disjoint?(Enum.into([1, 2], set_impl.new), Enum.into([2, 3], set_impl.new)) false """ @spec disjoint?(t, t) :: boolean def disjoint?(set1, set2) do target1 = target(set1) target2 = target(set2) if target1 == target2 do target1.disjoint?(set1, set2) else target2.reduce(set2, {:cont, true}, fn member, acc -> case target1.member?(set1, member) do false -> {:cont, acc} _ -> {:halt, false} end end) |> elem(1) end end @doc false @spec empty(t) :: t def empty(set) do target(set).empty(set) end @doc """ Checks if two sets are equal using `===`. Note that this function is polymorphic as it compares sets of any type. Each set implementation also provides an `equal?` function, but that function can only work with sets of the same type. ## Examples iex> Set.equal?(Enum.into([1, 2], set_impl.new), Enum.into([2, 1, 1], set_impl.new)) true iex> Set.equal?(Enum.into([1, 2], set_impl.new), Enum.into([3, 4], set_impl.new)) false """ @spec equal?(t, t) :: boolean def equal?(set1, set2) do target1 = target(set1) target2 = target(set2) cond do target1 == target2 -> target1.equal?(set1, set2) target1.size(set1) == target2.size(set2) -> do_subset?(target1, target2, set1, set2) true -> false end end @doc """ Returns a set containing only members that `set1` and `set2` have in common. Note that this function is polymorphic as it calculates the intersection of any type. Each set implementation also provides an `intersection` function, but that function can only work with sets of the same type. ## Examples iex> Set.intersection(Enum.into([1, 2], set_impl.new), Enum.into([2, 3, 4], set_impl.new)) |> Enum.sort [2] iex> Set.intersection(Enum.into([1, 2], set_impl.new), Enum.into([3, 4], set_impl.new)) |> Enum.sort [] """ @spec intersection(t, t) :: t def intersection(set1, set2) do target1 = target(set1) target2 = target(set2) if target1 == target2 do target1.intersection(set1, set2) else target1.reduce(set1, {:cont, target1.new}, fn v, acc -> {:cont, if(target2.member?(set2, v), do: target1.put(acc, v), else: acc)} end) |> elem(1) end end @doc """ Checks if `set` contains `value`. ## Examples iex> Set.member?(Enum.into([1, 2, 3], set_impl.new), 2) true iex> Set.member?(Enum.into([1, 2, 3], set_impl.new), 4) false """ @spec member?(t, value) :: boolean def member?(set, value) do target(set).member?(set, value) end @doc """ Inserts `value` into `set` if `set` doesn't already contain it. ## Examples iex> Set.put(Enum.into([1, 2, 3], set_impl.new), 3) |> Enum.sort [1, 2, 3] iex> Set.put(Enum.into([1, 2, 3], set_impl.new), 4) |> Enum.sort [1, 2, 3, 4] """ @spec put(t, value) :: t def put(set, value) do target(set).put(set, value) end @doc """ Returns the number of elements in `set`. ## Examples iex> Set.size(Enum.into([1, 2, 3], set_impl.new)) 3 """ @spec size(t) :: non_neg_integer def size(set) do target(set).size(set) end @doc """ Checks if `set1`'s members are all contained in `set2`. This function checks if `set1` is a subset of `set2`. Note that this function is polymorphic as it checks the subset for any type. Each set implementation also provides a `subset?` function, but that function can only work with sets of the same type. ## Examples iex> Set.subset?(Enum.into([1, 2], set_impl.new), Enum.into([1, 2, 3], set_impl.new)) true iex> Set.subset?(Enum.into([1, 2, 3], set_impl.new), Enum.into([1, 2], set_impl.new)) false """ @spec subset?(t, t) :: boolean def subset?(set1, set2) do target1 = target(set1) target2 = target(set2) if target1 == target2 do target1.subset?(set1, set2) else do_subset?(target1, target2, set1, set2) end end @doc """ Converts `set` to a list. ## Examples iex> set_impl.to_list(Enum.into([1, 2, 3], set_impl.new)) |> Enum.sort [1, 2, 3] """ @spec to_list(t) :: list def to_list(set) do target(set).to_list(set) end @doc """ Returns a set containing all members of `set1` and `set2`. Note that this function is polymorphic as it calculates the union of sets of any type. Each set implementation also provides a `union` function, but that function can only work with sets of the same type. ## Examples iex> Set.union(Enum.into([1, 2], set_impl.new), Enum.into([2, 3, 4], set_impl.new)) |> Enum.sort [1, 2, 3, 4] """ @spec union(t, t) :: t def union(set1, set2) do target1 = target(set1) target2 = target(set2) if target1 == target2 do target1.union(set1, set2) else target2.reduce(set2, {:cont, set1}, fn v, acc -> {:cont, target1.put(acc, v)} end) |> elem(1) end end defp do_subset?(target1, target2, set1, set2) do target1.reduce(set1, {:cont, true}, fn member, acc -> case target2.member?(set2, member) do true -> {:cont, acc} _ -> {:halt, false} end end) |> elem(1) end defp unsupported_set(set) do raise ArgumentError, "unsupported set: #{inspect set}" end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/stream.ex000066400000000000000000001062001254730255300215550ustar00rootroot00000000000000defmodule Stream do @moduledoc """ Module for creating and composing streams. Streams are composable, lazy enumerables. Any enumerable that generates items one by one during enumeration is called a stream. For example, Elixir's `Range` is a stream: iex> range = 1..5 1..5 iex> Enum.map range, &(&1 * 2) [2, 4, 6, 8, 10] In the example above, as we mapped over the range, the elements being enumerated were created one by one, during enumeration. The `Stream` module allows us to map the range, without triggering its enumeration: iex> range = 1..3 iex> stream = Stream.map(range, &(&1 * 2)) iex> Enum.map(stream, &(&1 + 1)) [3, 5, 7] Notice we started with a range and then we created a stream that is meant to multiply each item in the range by 2. At this point, no computation was done yet. Just when `Enum.map/2` is called we enumerate over each item in the range, multiplying it by 2 and adding 1. We say the functions in `Stream` are *lazy* and the functions in `Enum` are *eager*. Due to their laziness, streams are useful when working with large (or even infinite) collections. When chaining many operations with `Enum`, intermediate lists are created, while `Stream` creates a recipe of computations that are executed at a later moment. Let's see another example: 1..3 |> Enum.map(&IO.inspect(&1)) |> Enum.map(&(&1 * 2)) |> Enum.map(&IO.inspect(&1)) 1 2 3 2 4 6 #=> [2, 4, 6] Notice that we first printed each item in the list, then multiplied each element by 2 and finally printed each new value. In this example, the list was enumerated three times. Let's see an example with streams: stream = 1..3 |> Stream.map(&IO.inspect(&1)) |> Stream.map(&(&1 * 2)) |> Stream.map(&IO.inspect(&1)) Enum.to_list(stream) 1 2 2 4 3 6 #=> [2, 4, 6] Although the end result is the same, the order in which the items were printed changed! With streams, we print the first item and then print its double. In this example, the list was enumerated just once! That's what we meant when we first said that streams are composable, lazy enumerables. Notice we could call `Stream.map/2` multiple times, effectively composing the streams and they are lazy. The computations are performed only when you call a function from the `Enum` module. ## Creating Streams There are many functions in Elixir's standard library that return streams, some examples are: * `IO.stream/2` - streams input lines, one by one * `URI.query_decoder/1` - decodes a query string, pair by pair This module also provides many convenience functions for creating streams, like `Stream.cycle/1`, `Stream.unfold/2`, `Stream.resource/3` and more. Note the functions in this module are guaranteed to return enumerables. Since enumerables can have different shapes (structs, anonymous functions, and so on), the functions in this module may return any of those shapes and that it may change at any time. For example, a function that today returns an anonymous function may return a struct in future releases. """ @doc false defstruct enum: nil, funs: [], accs: [], done: nil @type acc :: any @type element :: any @type index :: non_neg_integer @type default :: any @type t :: %__MODULE__{} # Require Stream.Reducers and its callbacks require Stream.Reducers, as: R defmacrop skip(acc) do {:cont, acc} end defmacrop next(f, entry, acc) do quote do: unquote(f).(unquote(entry), unquote(acc)) end defmacrop acc(h, n, t) do quote do: [unquote(h), unquote(n)|unquote(t)] end defmacrop next_with_acc(f, entry, h, n, t) do quote do {reason, [h|t]} = unquote(f).(unquote(entry), [unquote(h)|unquote(t)]) {reason, [h, unquote(n)|t]} end end ## Transformers @doc """ Shortcut to `chunk(enum, n, n)`. """ @spec chunk(Enumerable.t, non_neg_integer) :: Enumerable.t def chunk(enum, n), do: chunk(enum, n, n, nil) @doc """ Streams the enumerable in chunks, containing `n` items each, where each new chunk starts `step` elements into the enumerable. `step` is optional and, if not passed, defaults to `n`, i.e. chunks do not overlap. If the final chunk does not have `n` elements to fill the chunk, elements are taken as necessary from `pad` if it was passed. If `pad` is passed and does not have enough elements to fill the chunk, then the chunk is returned anyway with less than `n` elements. If `pad` is not passed at all or is `nil`, then the partial chunk is discarded from the result. ## Examples iex> Stream.chunk([1, 2, 3, 4, 5, 6], 2) |> Enum.to_list [[1, 2], [3, 4], [5, 6]] iex> Stream.chunk([1, 2, 3, 4, 5, 6], 3, 2) |> Enum.to_list [[1, 2, 3], [3, 4, 5]] iex> Stream.chunk([1, 2, 3, 4, 5, 6], 3, 2, [7]) |> Enum.to_list [[1, 2, 3], [3, 4, 5], [5, 6, 7]] iex> Stream.chunk([1, 2, 3, 4, 5, 6], 3, 3, []) |> Enum.to_list [[1, 2, 3], [4, 5, 6]] """ @spec chunk(Enumerable.t, non_neg_integer, non_neg_integer) :: Enumerable.t @spec chunk(Enumerable.t, non_neg_integer, non_neg_integer, Enumerable.t | nil) :: Enumerable.t def chunk(enum, n, step, pad \\ nil) when n > 0 and step > 0 do limit = :erlang.max(n, step) if is_nil(pad) do lazy enum, {[], 0}, fn(f1) -> R.chunk(n, step, limit, f1) end else lazy enum, {[], 0}, fn(f1) -> R.chunk(n, step, limit, f1) end, &do_chunk(&1, n, pad, &2) end end defp do_chunk(acc(_, {_, 0}, _) = acc, _, _, _) do {:cont, acc} end defp do_chunk(acc(h, {buffer, count} = old, t), n, pad, f1) do buffer = :lists.reverse(buffer, Enum.take(pad, n - count)) next_with_acc(f1, buffer, h, old, t) end @doc """ Chunks the `enum` by buffering elements for which `fun` returns the same value and only emit them when `fun` returns a new value or the `enum` finishes. ## Examples iex> stream = Stream.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1)) iex> Enum.to_list(stream) [[1], [2, 2], [3], [4, 4, 6], [7, 7]] """ @spec chunk_by(Enumerable.t, (element -> any)) :: Enumerable.t def chunk_by(enum, fun) do lazy enum, nil, fn(f1) -> R.chunk_by(fun, f1) end, &do_chunk_by(&1, &2) end defp do_chunk_by(acc(_, nil, _) = acc, _f1) do {:cont, acc} end defp do_chunk_by(acc(h, {buffer, _}, t), f1) do next_with_acc(f1, :lists.reverse(buffer), h, nil, t) end @doc """ Creates a stream that only emits elements if they are different from the last emitted element. This function only ever needs to store the last emitted element. Elements are compared using `===`. ## Examples iex> Stream.dedup([1, 2, 3, 3, 2, 1]) |> Enum.to_list [1, 2, 3, 2, 1] """ @spec dedup(Enumerable.t) :: Enumerable.t def dedup(enum) do dedup_by(enum, fn x -> x end) end @doc """ Creates a stream that only emits elements if the result of calling `fun` on the element is different from the (stored) result of calling `fun` on the last emitted element. ## Examples iex> Stream.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) |> Enum.to_list [{1, :x}, {2, :y}, {1, :x}] """ @spec dedup_by(Enumerable.t, (element -> term)) :: Enumerable.t def dedup_by(enum, fun) when is_function(fun, 1) do lazy enum, nil, fn f1 -> R.dedup(fun, f1) end end @doc """ Lazily drops the next `n` items from the enumerable. If a negative `n` is given, it will drop the last `n` items from the collection. Note that the mechanism by which this is implemented will delay the emission of any item until `n` additional items have been emitted by the enum. ## Examples iex> stream = Stream.drop(1..10, 5) iex> Enum.to_list(stream) [6, 7, 8, 9, 10] iex> stream = Stream.drop(1..10, -5) iex> Enum.to_list(stream) [1, 2, 3, 4, 5] """ @spec drop(Enumerable.t, non_neg_integer) :: Enumerable.t def drop(enum, n) when n >= 0 do lazy enum, n, fn(f1) -> R.drop(f1) end end def drop(enum, n) when n < 0 do n = abs(n) lazy enum, {0, [], []}, fn(f1) -> fn entry, [h, {count, buf1, []} | t] -> do_drop(:cont, n, entry, h, count, buf1, [], t) entry, [h, {count, buf1, [next|buf2]} | t] -> {reason, [h|t]} = f1.(next, [h|t]) do_drop(reason, n, entry, h, count, buf1, buf2, t) end end end defp do_drop(reason, n, entry, h, count, buf1, buf2, t) do buf1 = [entry|buf1] count = count + 1 if count == n do {reason, [h, {0, [], :lists.reverse(buf1)}|t]} else {reason, [h, {count, buf1, buf2}|t]} end end @doc """ Lazily drops elements of the enumerable while the given function returns `true`. ## Examples iex> stream = Stream.drop_while(1..10, &(&1 <= 5)) iex> Enum.to_list(stream) [6, 7, 8, 9, 10] """ @spec drop_while(Enumerable.t, (element -> as_boolean(term))) :: Enumerable.t def drop_while(enum, fun) do lazy enum, true, fn(f1) -> R.drop_while(fun, f1) end end @doc """ Executes the given function for each item. Useful for adding side effects (like printing) to a stream. ## Examples iex> stream = Stream.each([1, 2, 3], fn(x) -> send self, x end) iex> Enum.to_list(stream) iex> receive do: (x when is_integer(x) -> x) 1 iex> receive do: (x when is_integer(x) -> x) 2 iex> receive do: (x when is_integer(x) -> x) 3 """ @spec each(Enumerable.t, (element -> term)) :: Enumerable.t def each(enum, fun) do lazy enum, fn(f1) -> fn(x, acc) -> fun.(x) f1.(x, acc) end end end @doc """ Creates a stream that will apply the given function on enumeration and flatten the result. ## Examples iex> stream = Stream.flat_map([1, 2, 3], fn(x) -> [x, x * 2] end) iex> Enum.to_list(stream) [1, 2, 2, 4, 3, 6] """ @spec flat_map(Enumerable.t, (element -> Enumerable.t)) :: Enumerable.t def flat_map(enum, mapper) do transform(enum, nil, fn val, nil -> {mapper.(val), nil} end) end @doc """ Creates a stream that filters elements according to the given function on enumeration. ## Examples iex> stream = Stream.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) iex> Enum.to_list(stream) [2] """ @spec filter(Enumerable.t, (element -> as_boolean(term))) :: Enumerable.t def filter(enum, fun) do lazy enum, fn(f1) -> R.filter(fun, f1) end end @doc """ Creates a stream that filters and then maps elements according to given functions. Exists for symmetry with `Enum.filter_map/3`. ## Examples iex> stream = Stream.filter_map(1..6, fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) iex> Enum.to_list(stream) [4, 8, 12] """ @spec filter_map(Enumerable.t, (element -> as_boolean(term)), (element -> any)) :: Enumerable.t def filter_map(enum, filter, mapper) do lazy enum, fn(f1) -> R.filter_map(filter, mapper, f1) end end @doc """ Creates a stream that emits a value after the given period `n` in milliseconds. The values emitted are an increasing counter starting at `0`. ## Examples iex> Stream.interval(10) |> Enum.take(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """ # TODO: Allow it to handle system messages. @spec interval(non_neg_integer) :: Enumerable.t def interval(n) do unfold 0, fn (count) -> :timer.sleep(n) {count, count + 1} end end @doc """ Injects the stream values into the given collectable as a side-effect. This function is often used with `run/1` since any evaluation is delayed until the stream is executed. See `run/1` for an example. """ @spec into(Enumerable.t, Collectable.t) :: Enumerable.t def into(enum, collectable, transform \\ fn x -> x end) do &do_into(enum, collectable, transform, &1, &2) end defp do_into(enum, collectable, transform, acc, fun) do {initial, into} = Collectable.into(collectable) composed = fn x, [acc|collectable] -> collectable = into.(collectable, {:cont, transform.(x)}) {reason, acc} = fun.(x, acc) {reason, [acc|collectable]} end do_into(&Enumerable.reduce(enum, &1, composed), initial, into, acc) end defp do_into(reduce, collectable, into, {command, acc}) do try do reduce.({command, [acc|collectable]}) catch kind, reason -> stacktrace = System.stacktrace into.(collectable, :halt) :erlang.raise(kind, reason, stacktrace) else {:suspended, [acc|collectable], continuation} -> {:suspended, acc, &do_into(continuation, collectable, into, &1)} {reason, [acc|collectable]} -> into.(collectable, :done) {reason, acc} end end @doc """ Creates a stream that will apply the given function on enumeration. ## Examples iex> stream = Stream.map([1, 2, 3], fn(x) -> x * 2 end) iex> Enum.to_list(stream) [2, 4, 6] """ @spec map(Enumerable.t, (element -> any)) :: Enumerable.t def map(enum, fun) do lazy enum, fn(f1) -> R.map(fun, f1) end end @doc """ Creates a stream that will reject elements according to the given function on enumeration. ## Examples iex> stream = Stream.reject([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) iex> Enum.to_list(stream) [1, 3] """ @spec reject(Enumerable.t, (element -> as_boolean(term))) :: Enumerable.t def reject(enum, fun) do lazy enum, fn(f1) -> R.reject(fun, f1) end end @doc """ Runs the given stream. This is useful when a stream needs to be run, for side effects, and there is no interest in its return result. ## Examples Open up a file, replace all `#` by `%` and stream to another file without loading the whole file in memory: stream = File.stream!("code") |> Stream.map(&String.replace(&1, "#", "%")) |> Stream.into(File.stream!("new")) |> Stream.run No computation will be done until we call one of the Enum functions or `Stream.run/1`. """ @spec run(Enumerable.t) :: :ok def run(stream) do _ = Enumerable.reduce(stream, {:cont, nil}, fn(_, _) -> {:cont, nil} end) :ok end @doc """ Creates a stream that applies the given function to each element, emits the result and uses the same result as the accumulator for the next computation. ## Examples iex> stream = Stream.scan(1..5, &(&1 + &2)) iex> Enum.to_list(stream) [1, 3, 6, 10, 15] """ @spec scan(Enumerable.t, (element, acc -> any)) :: Enumerable.t def scan(enum, fun) do lazy enum, :first, fn(f1) -> R.scan_2(fun, f1) end end @doc """ Creates a stream that applies the given function to each element, emits the result and uses the same result as the accumulator for the next computation. Uses the given `acc` as the starting value. ## Examples iex> stream = Stream.scan(1..5, 0, &(&1 + &2)) iex> Enum.to_list(stream) [1, 3, 6, 10, 15] """ @spec scan(Enumerable.t, acc, (element, acc -> any)) :: Enumerable.t def scan(enum, acc, fun) do lazy enum, acc, fn(f1) -> R.scan_3(fun, f1) end end @doc """ Lazily takes the next `n` items from the enumerable and stops enumeration. If a negative `n` is given, the last `n` values will be taken. For such, the collection is fully enumerated keeping up to `2 * n` elements in memory. Once the end of the collection is reached, the last `count` elements will be executed. Therefore, using a negative `n` on an infinite collection will never return. ## Examples iex> stream = Stream.take(1..100, 5) iex> Enum.to_list(stream) [1, 2, 3, 4, 5] iex> stream = Stream.take(1..100, -5) iex> Enum.to_list(stream) [96, 97, 98, 99, 100] iex> stream = Stream.cycle([1, 2, 3]) |> Stream.take(5) iex> Enum.to_list(stream) [1, 2, 3, 1, 2] """ @spec take(Enumerable.t, integer) :: Enumerable.t def take(_enum, 0), do: %Stream{enum: []} def take([], _n), do: %Stream{enum: []} def take(enum, n) when is_integer(n) and n > 0 do lazy enum, n, fn(f1) -> R.take(f1) end end def take(enum, n) when is_integer(n) and n < 0 do &Enumerable.reduce(Enum.take(enum, n), &1, &2) end @doc """ Creates a stream that takes every `n` item from the enumerable. The first item is always included, unless `n` is 0. `n` must be a non-negative integer, or `FunctionClauseError` will be thrown. ## Examples iex> stream = Stream.take_every(1..10, 2) iex> Enum.to_list(stream) [1, 3, 5, 7, 9] """ @spec take_every(Enumerable.t, non_neg_integer) :: Enumerable.t def take_every(enum, n) when is_integer(n) and n > 0 do lazy enum, n, fn(f1) -> R.take_every(n, f1) end end def take_every(_enum, 0), do: %Stream{enum: []} @doc """ Lazily takes elements of the enumerable while the given function returns `true`. ## Examples iex> stream = Stream.take_while(1..100, &(&1 <= 5)) iex> Enum.to_list(stream) [1, 2, 3, 4, 5] """ @spec take_while(Enumerable.t, (element -> as_boolean(term))) :: Enumerable.t def take_while(enum, fun) do lazy enum, fn(f1) -> R.take_while(fun, f1) end end @doc """ Creates a stream that emits a single value after `n` milliseconds. The value emitted is `0`. ## Examples iex> Stream.timer(10) |> Enum.to_list [0] """ @spec timer(non_neg_integer) :: Enumerable.t def timer(n) do take(interval(n), 1) end @doc """ Transforms an existing stream. It expects an accumulator and a function that receives each stream item and an accumulator, and must return a tuple containing a new stream (often a list) with the new accumulator or a tuple with `:halt` as first element and the accumulator as second. Note: this function is similar to `Enum.flat_map_reduce/3` except the latter returns both the flat list and accumulator, while this one returns only the stream. ## Examples `Stream.transform/3` is useful as it can be used as the basis to implement many of the functions defined in this module. For example, we can implement `Stream.take(enum, n)` as follows: iex> enum = 1..100 iex> n = 3 iex> stream = Stream.transform(enum, 0, fn i, acc -> ...> if acc < n, do: {[i], acc + 1}, else: {:halt, acc} ...> end) iex> Enum.to_list(stream) [1, 2, 3] """ @spec transform(Enumerable.t, acc, fun) :: Enumerable.t when fun: (element, acc -> {Enumerable.t, acc} | {:halt, acc}), acc: any def transform(enum, acc, reducer) do &do_transform(enum, acc, reducer, &1, &2) end defp do_transform(enumerables, user_acc, user, inner_acc, fun) do inner = &do_transform_each(&1, &2, fun) step = &do_transform_step(&1, &2) next = &Enumerable.reduce(enumerables, &1, step) do_transform(user_acc, user, fun, [], next, inner_acc, inner) end defp do_transform(user_acc, user, fun, next_acc, next, inner_acc, inner) do case next.({:cont, next_acc}) do {:suspended, [val|next_acc], next} -> try do user.(val, user_acc) catch kind, reason -> stacktrace = System.stacktrace next.({:halt, next_acc}) :erlang.raise(kind, reason, stacktrace) else {[], user_acc} -> do_transform(user_acc, user, fun, next_acc, next, inner_acc, inner) {list, user_acc} when is_list(list) -> do_list_transform(user_acc, user, fun, next_acc, next, inner_acc, inner, &Enumerable.List.reduce(list, &1, fun)) {:halt, _user_acc} -> next.({:halt, next_acc}) {:halted, elem(inner_acc, 1)} {other, user_acc} -> do_enum_transform(user_acc, user, fun, next_acc, next, inner_acc, inner, &Enumerable.reduce(other, &1, inner)) end {reason, _} -> {reason, elem(inner_acc, 1)} end end defp do_list_transform(user_acc, user, fun, next_acc, next, inner_acc, inner, reduce) do try do reduce.(inner_acc) catch kind, reason -> stacktrace = System.stacktrace next.({:halt, next_acc}) :erlang.raise(kind, reason, stacktrace) else {:done, acc} -> do_transform(user_acc, user, fun, next_acc, next, {:cont, acc}, inner) {:halted, acc} -> next.({:halt, next_acc}) {:halted, acc} {:suspended, acc, c} -> {:suspended, acc, &do_list_transform(user_acc, user, fun, next_acc, next, &1, inner, c)} end end defp do_enum_transform(user_acc, user, fun, next_acc, next, {op, inner_acc}, inner, reduce) do try do reduce.({op, [:outer|inner_acc]}) catch kind, reason -> stacktrace = System.stacktrace next.({:halt, next_acc}) :erlang.raise(kind, reason, stacktrace) else # Only take into account outer halts when the op is not halt itself. # Otherwise, we were the ones wishing to halt, so we should just stop. {:halted, [:outer|acc]} when op != :halt -> do_transform(user_acc, user, fun, next_acc, next, {:cont, acc}, inner) {:halted, [_|acc]} -> next.({:halt, next_acc}) {:halted, acc} {:done, [_|acc]} -> do_transform(user_acc, user, fun, next_acc, next, {:cont, acc}, inner) {:suspended, [_|acc], c} -> {:suspended, acc, &do_enum_transform(user_acc, user, fun, next_acc, next, &1, inner, c)} end end defp do_transform_each(x, [:outer|acc], f) do case f.(x, acc) do {:halt, res} -> {:halt, [:inner|res]} {op, res} -> {op, [:outer|res]} end end defp do_transform_step(x, acc) do {:suspend, [x|acc]} end @doc """ Creates a stream that only emits elements if they are unique. Keep in mind that, in order to know if an element is unique or not, this function needs to store all unique values emitted by the stream. Therefore, if the stream is infinite, the number of items stored will grow infinitely, never being garbage collected. ## Examples iex> Stream.uniq([1, 2, 3, 3, 2, 1]) |> Enum.to_list [1, 2, 3] iex> Stream.uniq([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) |> Enum.to_list [{1, :x}, {2, :y}] """ @spec uniq(Enumerable.t) :: Enumerable.t @spec uniq(Enumerable.t, (element -> term)) :: Enumerable.t def uniq(enum, fun \\ fn x -> x end) do lazy enum, HashSet.new, fn f1 -> R.uniq(fun, f1) end end @doc """ Creates a stream where each item in the enumerable will be wrapped in a tuple alongside its index. ## Examples iex> stream = Stream.with_index([1, 2, 3]) iex> Enum.to_list(stream) [{1, 0}, {2, 1}, {3, 2}] """ @spec with_index(Enumerable.t) :: Enumerable.t def with_index(enum) do lazy enum, 0, fn(f1) -> R.with_index(f1) end end ## Combiners @doc """ Creates a stream that enumerates each enumerable in an enumerable. ## Examples iex> stream = Stream.concat([1..3, 4..6, 7..9]) iex> Enum.to_list(stream) [1, 2, 3, 4, 5, 6, 7, 8, 9] """ @spec concat(Enumerable.t) :: Enumerable.t def concat(enumerables) do flat_map(enumerables, &(&1)) end @doc """ Creates a stream that enumerates the first argument, followed by the second. ## Examples iex> stream = Stream.concat(1..3, 4..6) iex> Enum.to_list(stream) [1, 2, 3, 4, 5, 6] iex> stream1 = Stream.cycle([1, 2, 3]) iex> stream2 = Stream.cycle([4, 5, 6]) iex> stream = Stream.concat(stream1, stream2) iex> Enum.take(stream, 6) [1, 2, 3, 1, 2, 3] """ @spec concat(Enumerable.t, Enumerable.t) :: Enumerable.t def concat(first, second) do flat_map([first, second], &(&1)) end @doc """ Zips two collections together, lazily. The zipping finishes as soon as any enumerable completes. ## Examples iex> concat = Stream.concat(1..3, 4..6) iex> cycle = Stream.cycle([:a, :b, :c]) iex> Stream.zip(concat, cycle) |> Enum.to_list [{1, :a}, {2, :b}, {3, :c}, {4, :a}, {5, :b}, {6, :c}] """ @spec zip(Enumerable.t, Enumerable.t) :: Enumerable.t def zip(left, right) do step = &do_zip_step(&1, &2) left_fun = &Enumerable.reduce(left, &1, step) right_fun = &Enumerable.reduce(right, &1, step) # Return a function as a lazy enumerator. &do_zip([{left_fun, []}, {right_fun, []}], &1, &2) end defp do_zip(zips, {:halt, acc}, _fun) do do_zip_close(zips) {:halted, acc} end defp do_zip(zips, {:suspend, acc}, fun) do {:suspended, acc, &do_zip(zips, &1, fun)} end defp do_zip(zips, {:cont, acc}, callback) do try do do_zip(zips, acc, callback, [], []) catch kind, reason -> stacktrace = System.stacktrace do_zip_close(zips) :erlang.raise(kind, reason, stacktrace) else {:next, buffer, acc} -> do_zip(buffer, acc, callback) {:done, _} = o -> o end end defp do_zip([{fun, fun_acc}|t], acc, callback, list, buffer) do case fun.({:cont, fun_acc}) do {:suspended, [i|fun_acc], fun} -> do_zip(t, acc, callback, [i|list], [{fun, fun_acc}|buffer]) {_, _} -> do_zip_close(:lists.reverse(buffer, t)) {:done, acc} end end defp do_zip([], acc, callback, list, buffer) do zipped = List.to_tuple(:lists.reverse(list)) {:next, :lists.reverse(buffer), callback.(zipped, acc)} end defp do_zip_close([]), do: :ok defp do_zip_close([{fun, acc}|t]) do fun.({:halt, acc}) do_zip_close(t) end defp do_zip_step(x, acc) do {:suspend, [x|acc]} end ## Sources @doc """ Creates a stream that cycles through the given enumerable, infinitely. ## Examples iex> stream = Stream.cycle([1, 2, 3]) iex> Enum.take(stream, 5) [1, 2, 3, 1, 2] """ @spec cycle(Enumerable.t) :: Enumerable.t def cycle(enumerable) def cycle(enumerable) when is_list(enumerable) do unfold {enumerable, enumerable}, fn {source, [h | t]} -> {h, {source, t}} {source = [h | t], []} -> {h, {source, t}} end end def cycle(enumerable) do fn acc, fun -> inner = &do_cycle_each(&1, &2, fun) outer = &Enumerable.reduce(enumerable, &1, inner) do_cycle(outer, outer, acc) end end defp do_cycle(_reduce, _cycle, {:halt, acc}) do {:halted, acc} end defp do_cycle(reduce, cycle, {:suspend, acc}) do {:suspended, acc, &do_cycle(reduce, cycle, &1)} end defp do_cycle(reduce, cycle, acc) do try do reduce.(acc) catch {:stream_cycle, acc} -> {:halted, acc} else {state, acc} when state in [:done, :halted] -> do_cycle(cycle, cycle, {:cont, acc}) {:suspended, acc, continuation} -> {:suspended, acc, &do_cycle(continuation, cycle, &1)} end end defp do_cycle_each(x, acc, f) do case f.(x, acc) do {:halt, h} -> throw({:stream_cycle, h}) {_, _} = o -> o end end @doc """ Emits a sequence of values, starting with `start_value`. Successive values are generated by calling `next_fun` on the previous value. ## Examples iex> Stream.iterate(0, &(&1+1)) |> Enum.take(5) [0, 1, 2, 3, 4] """ @spec iterate(element, (element -> element)) :: Enumerable.t def iterate(start_value, next_fun) do unfold({:ok, start_value}, fn {:ok, value} -> {value, {:next, value}} {:next, value} -> next = next_fun.(value) {next, {:next, next}} end) end @doc """ Returns a stream generated by calling `generator_fun` repeatedly. ## Examples iex> Stream.repeatedly(&:random.uniform/0) |> Enum.take(3) [0.4435846174457203, 0.7230402056221108, 0.94581636451987] """ @spec repeatedly((() -> element)) :: Enumerable.t def repeatedly(generator_fun) when is_function(generator_fun, 0) do &do_repeatedly(generator_fun, &1, &2) end defp do_repeatedly(generator_fun, {:suspend, acc}, fun) do {:suspended, acc, &do_repeatedly(generator_fun, &1, fun)} end defp do_repeatedly(_generator_fun, {:halt, acc}, _fun) do {:halted, acc} end defp do_repeatedly(generator_fun, {:cont, acc}, fun) do do_repeatedly(generator_fun, fun.(generator_fun.(), acc), fun) end @doc """ Emits a sequence of values for the given resource. Similar to `transform/2` but the initial accumulated value is computed lazily via `start_fun` and executes an `after_fun` at the end of enumeration (both in cases of success and failure). Successive values are generated by calling `next_fun` with the previous accumulator (the initial value being the result returned by `start_fun`) and it must return a tuple containing a list of items to be emitted and the next accumulator. The enumeration finishes if it returns `{:halt, acc}`. As the name says, this function is useful to stream values from resources. ## Examples Stream.resource(fn -> File.open!("sample") end, fn file -> case IO.read(file, :line) do data when is_binary(data) -> {[data], file} _ -> {:halt, file} end end, fn file -> File.close(file) end) """ @spec resource((() -> acc), (acc -> {element, acc} | nil), (acc -> term)) :: Enumerable.t def resource(start_fun, next_fun, after_fun) do &do_resource(start_fun.(), next_fun, &1, &2, after_fun) end defp do_resource(next_acc, next_fun, {:suspend, acc}, fun, after_fun) do {:suspended, acc, &do_resource(next_acc, next_fun, &1, fun, after_fun)} end defp do_resource(next_acc, _next_fun, {:halt, acc}, _fun, after_fun) do after_fun.(next_acc) {:halted, acc} end defp do_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun) do try do # Optimize the most common cases case next_fun.(next_acc) do {[], next_acc} -> {:opt, {:cont, acc}, next_acc} {[v], next_acc} -> {:opt, fun.(v, acc), next_acc} {_, _} = other -> other end catch kind, reason -> stacktrace = System.stacktrace after_fun.(next_acc) :erlang.raise(kind, reason, stacktrace) else {:opt, acc, next_acc} -> do_resource(next_acc, next_fun, acc, fun, after_fun) {:halt, next_acc} -> do_resource(next_acc, next_fun, {:halt, acc}, fun, after_fun) {list, next_acc} when is_list(list) -> do_list_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun, &Enumerable.List.reduce(list, &1, fun)) {enum, next_acc} -> inner = &do_resource_each(&1, &2, fun) do_enum_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun, &Enumerable.reduce(enum, &1, inner)) end end defp do_list_resource(next_acc, next_fun, acc, fun, after_fun, reduce) do try do reduce.(acc) catch kind, reason -> stacktrace = System.stacktrace after_fun.(next_acc) :erlang.raise(kind, reason, stacktrace) else {:done, acc} -> do_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun) {:halted, acc} -> do_resource(next_acc, next_fun, {:halt, acc}, fun, after_fun) {:suspended, acc, c} -> {:suspended, acc, &do_list_resource(next_acc, next_fun, &1, fun, after_fun, c)} end end defp do_enum_resource(next_acc, next_fun, {op, acc}, fun, after_fun, reduce) do try do reduce.({op, [:outer|acc]}) catch kind, reason -> stacktrace = System.stacktrace after_fun.(next_acc) :erlang.raise(kind, reason, stacktrace) else {:halted, [:outer|acc]} -> do_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun) {:halted, [:inner|acc]} -> do_resource(next_acc, next_fun, {:halt, acc}, fun, after_fun) {:done, [_|acc]} -> do_resource(next_acc, next_fun, {:cont, acc}, fun, after_fun) {:suspended, [_|acc], c} -> {:suspended, acc, &do_enum_resource(next_acc, next_fun, &1, fun, after_fun, c)} end end defp do_resource_each(x, [:outer|acc], f) do case f.(x, acc) do {:halt, res} -> {:halt, [:inner|res]} {op, res} -> {op, [:outer|res]} end end @doc """ Emits a sequence of values for the given accumulator. Successive values are generated by calling `next_fun` with the previous accumulator and it must return a tuple with the current value and next accumulator. The enumeration finishes if it returns `nil`. ## Examples iex> Stream.unfold(5, fn 0 -> nil; n -> {n, n-1} end) |> Enum.to_list() [5, 4, 3, 2, 1] """ @spec unfold(acc, (acc -> {element, acc} | nil)) :: Enumerable.t def unfold(next_acc, next_fun) do &do_unfold(next_acc, next_fun, &1, &2) end defp do_unfold(next_acc, next_fun, {:suspend, acc}, fun) do {:suspended, acc, &do_unfold(next_acc, next_fun, &1, fun)} end defp do_unfold(_next_acc, _next_fun, {:halt, acc}, _fun) do {:halted, acc} end defp do_unfold(next_acc, next_fun, {:cont, acc}, fun) do case next_fun.(next_acc) do nil -> {:done, acc} {v, next_acc} -> do_unfold(next_acc, next_fun, fun.(v, acc), fun) end end ## Helpers @compile {:inline, lazy: 2, lazy: 3, lazy: 4} defp lazy(%Stream{done: nil, funs: funs} = lazy, fun), do: %{lazy | funs: [fun|funs] } defp lazy(enum, fun), do: %Stream{enum: enum, funs: [fun]} defp lazy(%Stream{done: nil, funs: funs, accs: accs} = lazy, acc, fun), do: %{lazy | funs: [fun|funs], accs: [acc|accs] } defp lazy(enum, acc, fun), do: %Stream{enum: enum, funs: [fun], accs: [acc]} defp lazy(%Stream{done: nil, funs: funs, accs: accs} = lazy, acc, fun, done), do: %{lazy | funs: [fun|funs], accs: [acc|accs], done: done} defp lazy(enum, acc, fun, done), do: %Stream{enum: enum, funs: [fun], accs: [acc], done: done} end defimpl Enumerable, for: Stream do @compile :inline_list_funs def reduce(lazy, acc, fun) do do_reduce(lazy, acc, fn x, [acc] -> {reason, acc} = fun.(x, acc) {reason, [acc]} end) end def count(_lazy) do {:error, __MODULE__} end def member?(_lazy, _value) do {:error, __MODULE__} end defp do_reduce(%Stream{enum: enum, funs: funs, accs: accs, done: done}, acc, fun) do composed = :lists.foldl(fn fun, acc -> fun.(acc) end, fun, funs) do_each(&Enumerable.reduce(enum, &1, composed), done && {done, fun}, :lists.reverse(accs), acc) end defp do_each(reduce, done, accs, {command, acc}) do case reduce.({command, [acc|accs]}) do {:suspended, [acc|accs], continuation} -> {:suspended, acc, &do_each(continuation, done, accs, &1)} {:halted, accs} -> do_done {:halted, accs}, done {:done, accs} -> do_done {:done, accs}, done end end defp do_done({reason, [acc|_]}, nil), do: {reason, acc} defp do_done({reason, [acc|t]}, {done, fun}) do [h|_] = Enum.reverse(t) case done.([acc, h], fun) do {:cont, [acc|_]} -> {reason, acc} {:halt, [acc|_]} -> {:halted, acc} {:suspend, [acc|_]} -> {:suspended, acc, &({:done, elem(&1, 1)})} end end end defimpl Inspect, for: Stream do import Inspect.Algebra def inspect(%{enum: enum, funs: funs}, opts) do inner = [enum: enum, funs: Enum.reverse(funs)] concat ["#Stream<", to_doc(inner, opts), ">"] end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/stream/000077500000000000000000000000001254730255300212205ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/stream/reducers.ex000066400000000000000000000113501254730255300233720ustar00rootroot00000000000000defmodule Stream.Reducers do # Collection of reducers shared by Enum and Stream. @moduledoc false defmacro chunk(n, step, limit, f \\ nil) do quote do fn entry, acc(h, {buffer, count}, t) -> buffer = [entry|buffer] count = count + 1 new = if count >= unquote(limit) do left = count - unquote(step) {Enum.take(buffer, left), left} else {buffer, count} end if count == unquote(n) do next_with_acc(unquote(f), :lists.reverse(buffer), h, new, t) else skip(acc(h, new, t)) end end end end defmacro chunk_by(callback, f \\ nil) do quote do fn entry, acc(h, {buffer, value}, t) -> new_value = unquote(callback).(entry) if new_value == value do skip(acc(h, {[entry|buffer], value}, t)) else next_with_acc(unquote(f), :lists.reverse(buffer), h, {[entry], new_value}, t) end entry, acc(h, nil, t) -> skip(acc(h, {[entry], unquote(callback).(entry)}, t)) end end end defmacro dedup(callback, f \\ nil) do quote do fn(entry, acc(h, prev, t) = acc) -> value = unquote(callback).(entry) case prev do {:value, ^value} -> skip(acc) _ -> next_with_acc(unquote(f), entry, h, {:value, value}, t) end end end end defmacro drop(f \\ nil) do quote do fn _entry, acc(h, n, t) when n > 0 -> skip(acc(h, n-1, t)) entry, acc(h, n, t) -> next_with_acc(unquote(f), entry, h, n, t) end end end defmacro drop_while(callback, f \\ nil) do quote do fn entry, acc(h, bool, t) = orig -> if bool and unquote(callback).(entry) do skip(orig) else next_with_acc(unquote(f), entry, h, false, t) end end end end defmacro filter(callback, f \\ nil) do quote do fn(entry, acc) -> if unquote(callback).(entry) do next(unquote(f), entry, acc) else skip(acc) end end end end defmacro filter_map(filter, mapper, f \\ nil) do quote do fn(entry, acc) -> if unquote(filter).(entry) do next(unquote(f), unquote(mapper).(entry), acc) else skip(acc) end end end end defmacro map(callback, f \\ nil) do quote do fn(entry, acc) -> next(unquote(f), unquote(callback).(entry), acc) end end end defmacro reject(callback, f \\ nil) do quote do fn(entry, acc) -> unless unquote(callback).(entry) do next(unquote(f), entry, acc) else skip(acc) end end end end defmacro scan_2(callback, f \\ nil) do quote do fn entry, acc(h, :first, t) -> next_with_acc(unquote(f), entry, h, {:ok, entry}, t) entry, acc(h, {:ok, acc}, t) -> value = unquote(callback).(entry, acc) next_with_acc(unquote(f), value, h, {:ok, value}, t) end end end defmacro scan_3(callback, f \\ nil) do quote do fn(entry, acc(h, acc, t)) -> value = unquote(callback).(entry, acc) next_with_acc(unquote(f), value, h, value, t) end end end defmacro take(f \\ nil) do quote do fn(entry, acc(h, n, t) = orig) -> case n do 0 -> {:halt, orig} 1 -> case next_with_acc(unquote(f), entry, h, n-1, t) do {:cont, acc} -> {:halt, acc} reason -> reason end _ -> next_with_acc(unquote(f), entry, h, n-1, t) end end end end defmacro take_every(nth, f \\ nil) do quote do fn entry, acc(h, n, t) when n === :first when n === unquote(nth) -> next_with_acc(unquote(f), entry, h, 1, t) entry, acc(h, n, t) -> skip(acc(h, n+1, t)) end end end defmacro take_while(callback, f \\ nil) do quote do fn(entry, acc) -> if unquote(callback).(entry) do next(unquote(f), entry, acc) else {:halt, acc} end end end end defmacro uniq(callback, f \\ nil) do quote do fn(entry, acc(h, prev, t) = acc) -> value = unquote(callback).(entry) if HashSet.member?(prev, value) do skip(acc) else next_with_acc(unquote(f), entry, h, HashSet.put(prev, value), t) end end end end defmacro with_index(f \\ nil) do quote do fn(entry, acc(h, counter, t)) -> next_with_acc(unquote(f), {entry, counter}, h, counter + 1, t) end end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/string.ex000066400000000000000000001214511254730255300215750ustar00rootroot00000000000000import Kernel, except: [length: 1] defmodule String do @moduledoc ~S""" A String in Elixir is a UTF-8 encoded binary. ## Codepoints and graphemes The functions in this module act according to the Unicode Standard, version 6.3.0. As per the standard, a codepoint is an Unicode Character, which may be represented by one or more bytes. For example, the character "é" is represented with two bytes: iex> byte_size("é") 2 However, this module returns the proper length: iex> String.length("é") 1 Furthermore, this module also presents the concept of graphemes, which are multiple characters that may be "perceived as a single character" by readers. For example, the same "é" character written above could be represented by the letter "e" followed by the accent ́: iex> string = "\x{0065}\x{0301}" iex> byte_size(string) 3 iex> String.length(string) 1 Although the example above is made of two characters, it is perceived by users as one. Graphemes can also be two characters that are interpreted as one by some languages. For example, some languages may consider "ch" as a grapheme. However, since this information depends on the locale, it is not taken into account by this module. In general, the functions in this module rely on the Unicode Standard, but do not contain any of the locale specific behaviour. More information about graphemes can be found in the [Unicode Standard Annex #29](http://www.unicode.org/reports/tr29/). This current Elixir version implements Extended Grapheme Cluster algorithm. ## String and binary operations To act accordingly to the Unicode Standard, many functions in this module runs in linear time, as it needs to traverse the whole string considering the proper Unicode codepoints. For example, `String.length/1` is going to take longer as the input grows. On the other hand, `Kernel.byte_size/1` always runs in constant time (i.e. regardless of the input size). This means often there are performance costs in using the functions in this module, compared to the more low-level operations that work directly with binaries: * `Kernel.binary_part/3` - retrieves part of the binary * `Kernel.bit_size/1` and `Kernel.byte_size/1` - size related functions * `Kernel.is_bitstring/1` and `Kernel.is_binary/1` - type checking function * Plus a number of functions for working with binaries (bytes) [in the `:binary` module](http://erlang.org/doc/man/binary.html) There are many situations where using the `String` module can be avoided in favor of binary functions or pattern matching. For example, imagine you have a string `prefix` and you want to remove this prefix from another string named `full`. One may be tempted to write: iex> take_prefix = fn full, prefix -> ...> base = String.length(prefix) ...> String.slice(full, base, String.length(full) - base) ...> end iex> take_prefix.("Mr. John", "Mr. ") "John" Although the function above works, it performs poorly. To calculate the length of the string, we need to traverse it fully, so we traverse both `prefix` and `full` strings, then slice the `full` one, traversing it again. A first attempting at improving it could be with ranges: iex> take_prefix = fn full, prefix -> ...> base = String.length(prefix) ...> String.slice(full, base..-1) ...> end iex> take_prefix.("Mr. John", "Mr. ") "John" While this is much better (we don't traverse `full` twice), it could still be improved. In this case, since we want to extract a substring from a string, we can use `byte_size/1` and `binary_part/3` as there is no chance we will slice in the middle of a codepoint made of more than one byte: iex> take_prefix = fn full, prefix -> ...> base = byte_size(prefix) ...> binary_part(full, base, byte_size(full) - base) ...> end iex> take_prefix.("Mr. John", "Mr. ") "John" Or simply use pattern matching: iex> take_prefix = fn full, prefix -> ...> base = byte_size(prefix) ...> <<_ :: binary-size(base), rest :: binary>> = full ...> rest ...> end iex> take_prefix.("Mr. John", "Mr. ") "John" On the other hand, if you want to dynamically slice a string based on an integer value, then using `String.slice/3` is the best option as it guarantees we won't incorrectly split a valid codepoint in multiple bytes. ## Integer codepoints Although codepoints could be represented as integers, this module represents all codepoints as strings. For example: iex> String.codepoints("olá") ["o", "l", "á"] There are a couple of ways to retrieve a character integer codepoint. One may use the `?` construct: iex> ?o 111 iex> ?á 225 Or also via pattern matching: iex> << eacute :: utf8 >> = "á" iex> eacute 225 As we have seen above, codepoints can be inserted into a string by their hexadecimal code: "ol\x{0061}\x{0301}" #=> "olá" ## Self-synchronization The UTF-8 encoding is self-synchronizing. This means that if malformed data (i.e., data that is not possible according to the definition of the encoding) is encountered, only one codepoint needs to be rejected. This module relies on this behaviour to ignore such invalid characters. For example, `length/1` is going to return a correct result even if an invalid codepoint is fed into it. In other words, this module expects invalid data to be detected when retrieving data from the external source. For example, a driver that reads strings from a database will be the one responsible to check the validity of the encoding. ## Patterns Many functions in this module work with patterns. For example, String.split/2 can split a string into multiple patterns given a pattern. This pattern can be a string, a list of strings or a compiled pattern: iex> String.split("foo bar", " ") ["foo", "bar"] iex> String.split("foo bar!", [" ", "!"]) ["foo", "bar", ""] iex> pattern = :binary.compile_pattern([" ", "!"]) iex> String.split("foo bar!", pattern) ["foo", "bar", ""] The compiled pattern is useful when the same match will be done over and over again. Note though the compiled pattern cannot be stored in a module attribute as the pattern is generated at runtime and does not survive compile term. """ @type t :: binary @type codepoint :: t @type grapheme :: t @type pattern :: t | [t] | :binary.cp @doc """ Checks if a string is printable considering it is encoded as UTF-8. Returns `true` if so, `false` otherwise. ## Examples iex> String.printable?("abc") true """ @spec printable?(t) :: boolean def printable?(string) def printable?(<< h :: utf8, t :: binary >>) when h in 0x20..0x7E when h in 0xA0..0xD7FF when h in 0xE000..0xFFFD when h in 0x10000..0x10FFFF do printable?(t) end def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<>), do: printable?(t) def printable?(<<>>), do: true def printable?(binary) when is_binary(binary), do: false @doc """ Divides a string into substrings at each Unicode whitespace occurrence with leading and trailing whitespace ignored. ## Examples iex> String.split("foo bar") ["foo", "bar"] iex> String.split("foo" <> <<194, 133>> <> "bar") ["foo", "bar"] iex> String.split(" foo bar ") ["foo", "bar"] """ @spec split(t) :: [t] defdelegate split(binary), to: String.Unicode @doc ~S""" Divides a string into substrings based on a pattern. Returns a list of these substrings. The pattern can be a string, a list of strings or a regular expression. The string is split into as many parts as possible by default, but can be controlled via the `parts: num` option. If you pass `parts: :infinity`, it will return all possible parts (being this one the default behaviour). Empty strings are only removed from the result if the `trim` option is set to `true` (default is `false`). ## Examples Splitting with a string pattern: iex> String.split("a,b,c", ",") ["a", "b", "c"] iex> String.split("a,b,c", ",", parts: 2) ["a", "b,c"] iex> String.split(" a b c ", " ", trim: true) ["a", "b", "c"] A list of patterns: iex> String.split("1,2 3,4", [" ", ","]) ["1", "2", "3", "4"] A regular expression: iex> String.split("a,b,c", ~r{,}) ["a", "b", "c"] iex> String.split("a,b,c", ~r{,}, parts: 2) ["a", "b,c"] iex> String.split(" a b c ", ~r{\s}, trim: true) ["a", "b", "c"] Splitting on empty patterns returns codepoints: iex> String.split("abc", ~r{}) ["a", "b", "c", ""] iex> String.split("abc", "") ["a", "b", "c", ""] iex> String.split("abc", "", trim: true) ["a", "b", "c"] iex> String.split("abc", "", parts: 2) ["a", "bc"] A precompiled pattern can also be given: iex> pattern = :binary.compile_pattern([" ", ","]) iex> String.split("1,2 3,4", pattern) ["1", "2", "3", "4"] """ @spec split(t, pattern | Regex.t) :: [t] @spec split(t, pattern | Regex.t, Keyword.t) :: [t] def split(string, pattern, options \\ []) def split(string, %Regex{} = pattern, options) do Regex.split(pattern, string, options) end def split(string, pattern, []) when pattern != "" do :binary.split(string, pattern, [:global]) end def split(string, pattern, options) do parts = Keyword.get(options, :parts, :infinity) trim = Keyword.get(options, :trim, false) pattern = maybe_compile_pattern(pattern) split_each(string, pattern, trim, parts_to_index(parts)) end defp parts_to_index(:infinity), do: 0 defp parts_to_index(n) when is_integer(n) and n > 0, do: n defp split_each(string, _pattern, _trim, 1) when is_binary(string), do: [string] defp split_each(string, pattern, trim, count) do case do_splitter(string, pattern, trim) do {h, t} -> [h|split_each(t, pattern, trim, count - 1)] nil -> [] end end @doc """ Splits a string on demand. Returns an enumerable that splits the string on demand, instead of splitting all data upfront. Note splitter does not support regular expressions (as it is often more efficient to have the regular expressions traverse the string at once than in multiple passes). ## Options * :trim - when true, does not emit empty patterns """ @spec splitter(t, pattern, Keyword.t) :: Enumerable.t def splitter(string, pattern, options \\ []) do pattern = maybe_compile_pattern(pattern) trim = Keyword.get(options, :trim, false) Stream.unfold(string, &do_splitter(&1, pattern, trim)) end defp do_splitter(:nomatch, _pattern, _), do: nil defp do_splitter("", _pattern, true), do: nil defp do_splitter("", _pattern, false), do: {"", :nomatch} defp do_splitter(bin, "", _trim) do next_grapheme(bin) end defp do_splitter(bin, pattern, trim) do case :binary.match(bin, pattern) do {0, length} when trim -> do_splitter(:binary.part(bin, length, byte_size(bin) - length), pattern, trim) {pos, length} -> final = pos + length {:binary.part(bin, 0, pos), :binary.part(bin, final, byte_size(bin) - final)} :nomatch -> {bin, :nomatch} end end defp maybe_compile_pattern(""), do: "" defp maybe_compile_pattern(pattern), do: :binary.compile_pattern(pattern) @doc """ Splits a string into two at the specified offset. When the offset given is negative, location is counted from the end of the string. The offset is capped to the length of the string. Returns a tuple with two elements. Note: keep in mind this function splits on graphemes and for such it has to linearly traverse the string. If you want to split a string or a binary based on the number of bytes, use `Kernel.binary_part/3` instead. ## Examples iex> String.split_at "sweetelixir", 5 {"sweet", "elixir"} iex> String.split_at "sweetelixir", -6 {"sweet", "elixir"} iex> String.split_at "abc", 0 {"", "abc"} iex> String.split_at "abc", 1000 {"abc", ""} iex> String.split_at "abc", -1000 {"", "abc"} """ @spec split_at(t, integer) :: {t, t} def split_at(string, offset) def split_at(binary, 0), do: {"", binary} def split_at(binary, index) when is_integer(index) and index > 0, do: do_split_at(next_grapheme(binary), 0, index, "") def split_at(binary, index) when is_integer(index) and index < 0, do: do_split_at(next_grapheme(binary), 0, max(0, byte_size(binary)+index), "") defp do_split_at(nil, _, _, acc), do: {acc, ""} defp do_split_at({grapheme, rest}, current_pos, target_pos, acc) when current_pos < target_pos, do: do_split_at(next_grapheme(rest), current_pos+1, target_pos, acc <> grapheme) defp do_split_at({grapheme, rest}, pos, pos, acc), do: {acc, grapheme <> rest} @doc """ Converts all characters in the given string to uppercase. ## Examples iex> String.upcase("abcd") "ABCD" iex> String.upcase("ab 123 xpto") "AB 123 XPTO" iex> String.upcase("olá") "OLÁ" """ @spec upcase(t) :: t defdelegate upcase(binary), to: String.Unicode @doc """ Converts all characters in the given string to lowercase. ## Examples iex> String.downcase("ABCD") "abcd" iex> String.downcase("AB 123 XPTO") "ab 123 xpto" iex> String.downcase("OLÁ") "olá" """ @spec downcase(t) :: t defdelegate downcase(binary), to: String.Unicode @doc """ Converts the first character in the given string to uppercase and the remainder to lowercase. This relies on the titlecase information provided by the Unicode Standard. Note this function makes no attempt to capitalize all words in the string (usually known as titlecase). ## Examples iex> String.capitalize("abcd") "Abcd" iex> String.capitalize("fin") "Fin" iex> String.capitalize("olá") "Olá" """ @spec capitalize(t) :: t def capitalize(string) when is_binary(string) do {char, rest} = String.Unicode.titlecase_once(string) char <> downcase(rest) end @doc """ Returns a string where trailing Unicode whitespace has been removed. ## Examples iex> String.rstrip(" abc ") " abc" """ @spec rstrip(t) :: t defdelegate rstrip(binary), to: String.Unicode @doc """ Returns a string where trailing `char` have been removed. ## Examples iex> String.rstrip(" abc _", ?_) " abc " """ @spec rstrip(t, char) :: t def rstrip("", _char), do: "" # Do a quick check before we traverse the whole # binary. :binary.last is a fast operation (it # does not traverse the whole binary). def rstrip(string, char) when char in 0..127 do if :binary.last(string) == char do rstrip(binary_part(string, 0, byte_size(string) - 1), char) else string end end def rstrip(string, char) when is_integer(char) do do_rstrip(string, "", char) end defp do_rstrip(<>, buffer, char) do <>, char) :: binary>> end defp do_rstrip(<>, buffer, another_char) do <> end defp do_rstrip(<<>>, _, _) do <<>> end @doc """ Returns a string where leading Unicode whitespace has been removed. ## Examples iex> String.lstrip(" abc ") "abc " """ defdelegate lstrip(binary), to: String.Unicode @doc """ Returns a string where leading `char` have been removed. ## Examples iex> String.lstrip("_ abc _", ?_) " abc _" """ @spec lstrip(t, char) :: t def lstrip(string, char) def lstrip(<>, char) when is_integer(char) do <> end def lstrip(string, char) when is_integer(char) do string end @doc """ Returns a string where leading and trailing Unicode whitespace has been removed. ## Examples iex> String.strip(" abc ") "abc" """ @spec strip(t) :: t def strip(string) do rstrip(lstrip(string)) end @doc """ Returns a string where leading and trailing `char` have been removed. ## Examples iex> String.strip("a abc a", ?a) " abc " """ @spec strip(t, char) :: t def strip(string, char) do rstrip(lstrip(string, char), char) end @doc ~S""" Returns a new string of length `len` with `subject` right justified and padded with `padding`. If `padding` is not present, it defaults to whitespace. When `len` is less than the length of `subject`, `subject` is returned. ## Examples iex> String.rjust("abc", 5) " abc" iex> String.rjust("abc", 5, ?-) "--abc" """ @spec rjust(t, non_neg_integer) :: t @spec rjust(t, non_neg_integer, char) :: t def rjust(subject, len, pad \\ ?\s) when is_integer(pad) and is_integer(len) and len >= 0 do justify(subject, len, pad, :right) end @doc ~S""" Returns a new string of length `len` with `subject` left justified and padded with `padding`. If `padding` is not present, it defaults to whitespace. When `len` is less than the length of `subject`, `subject` is returned. ## Examples iex> String.ljust("abc", 5) "abc " iex> String.ljust("abc", 5, ?-) "abc--" """ @spec ljust(t, non_neg_integer) :: t @spec ljust(t, non_neg_integer, char) :: t def ljust(subject, len, pad \\ ?\s) when is_integer(pad) and is_integer(len) and len >= 0 do justify(subject, len, pad, :left) end defp justify(subject, 0, _pad, _type), do: subject defp justify(subject, len, padding, type) do subject_len = length(subject) cond do subject_len >= len -> subject subject_len < len -> fill = duplicate(<>, len - subject_len) case type do :left -> subject <> fill :right -> fill <> subject end end end @doc ~S""" Returns a new binary created by replacing occurences of `pattern` in `subject` with `replacement`. By default, it replaces all occurences, except if the `global` option is set to `false`. A `pattern` may be a string or a regular expression. ## Examples iex> String.replace("a,b,c", ",", "-") "a-b-c" iex> String.replace("a,b,c", ",", "-", global: false) "a-b,c" The pattern can also be a regular expression. In those cases, one can give `\N` or `\g{N}` in the `replacement` string to access a specific capture in the regex: iex> String.replace("a,b,c", ~r/,(.)/, ",\\1\\1") "a,bb,cc" Notice we had to escape the escape character `\`. By giving `\0`, one can inject the whole matched pattern in the replacement string. When strings are used as a pattern, a developer can also use the replaced part inside the `replacement` via the `:insert_replaced` option: iex> String.replace("a,b,c", "b", "[]", insert_replaced: 1) "a,[b],c" iex> String.replace("a,b,c", ",", "[]", insert_replaced: 2) "a[],b[],c" iex> String.replace("a,b,c", ",", "[]", insert_replaced: [1, 1]) "a[,,]b[,,]c" """ @spec replace(t, pattern | Regex.t, t, Keyword.t) :: t def replace(subject, pattern, replacement, options \\ []) when is_binary(replacement) do if Regex.regex?(pattern) do Regex.replace(pattern, subject, replacement, global: options[:global]) else opts = translate_replace_options(options) :binary.replace(subject, pattern, replacement, opts) end end defp translate_replace_options(options) do opts = if Keyword.get(options, :global) != false, do: [:global], else: [] if insert = Keyword.get(options, :insert_replaced) do opts = [{:insert_replaced, insert}|opts] end opts end @doc """ Reverses the given string. Works on graphemes. ## Examples iex> String.reverse("abcd") "dcba" iex> String.reverse("hello world") "dlrow olleh" iex> String.reverse("hello ∂og") "go∂ olleh" """ @spec reverse(t) :: t def reverse(string) do do_reverse(next_grapheme(string), []) end defp do_reverse({grapheme, rest}, acc) do do_reverse(next_grapheme(rest), [grapheme|acc]) end defp do_reverse(nil, acc), do: IO.iodata_to_binary(acc) @doc """ Returns a binary `subject` duplicated `n` times. ## Examples iex> String.duplicate("abc", 0) "" iex> String.duplicate("abc", 1) "abc" iex> String.duplicate("abc", 2) "abcabc" """ @spec duplicate(t, non_neg_integer) :: t def duplicate(subject, n) when is_integer(n) and n >= 0 do :binary.copy(subject, n) end @doc """ Returns all codepoints in the string. ## Examples iex> String.codepoints("olá") ["o", "l", "á"] iex> String.codepoints("оптими зации") ["о", "п", "т", "и", "м", "и", " ", "з", "а", "ц", "и", "и"] iex> String.codepoints("ἅἪῼ") ["ἅ", "Ἢ", "ῼ"] """ @spec codepoints(t) :: [codepoint] defdelegate codepoints(string), to: String.Unicode @doc """ Returns the next codepoint in a String. The result is a tuple with the codepoint and the remainder of the string or `nil` in case the string reached its end. As with other functions in the String module, this function does not check for the validity of the codepoint. That said, if an invalid codepoint is found, it will be returned by this function. ## Examples iex> String.next_codepoint("olá") {"o", "lá"} """ @compile {:inline, next_codepoint: 1} @spec next_codepoint(t) :: {codepoint, t} | nil defdelegate next_codepoint(string), to: String.Unicode @doc ~S""" Checks whether `str` contains only valid characters. ## Examples iex> String.valid?("a") true iex> String.valid?("ø") true iex> String.valid?(<<0xffff :: 16>>) false iex> String.valid?("asd" <> <<0xffff :: 16>>) false """ @spec valid?(t) :: boolean def valid?(string) noncharacters = Enum.to_list(?\x{FDD0}..?\x{FDEF}) ++ [ ?\x{0FFFE}, ?\x{0FFFF}, ?\x{1FFFE}, ?\x{1FFFF}, ?\x{2FFFE}, ?\x{2FFFF}, ?\x{3FFFE}, ?\x{3FFFF}, ?\x{4FFFE}, ?\x{4FFFF}, ?\x{5FFFE}, ?\x{5FFFF}, ?\x{6FFFE}, ?\x{6FFFF}, ?\x{7FFFE}, ?\x{7FFFF}, ?\x{8FFFE}, ?\x{8FFFF}, ?\x{9FFFE}, ?\x{9FFFF}, ?\x{10FFFE}, ?\x{10FFFF} ] for noncharacter <- noncharacters do def valid?(<< unquote(noncharacter) :: utf8, _ :: binary >>), do: false end def valid?(<<_ :: utf8, t :: binary>>), do: valid?(t) def valid?(<<>>), do: true def valid?(_), do: false @doc ~S""" Checks whether `string` is a valid character. All characters are codepoints, but some codepoints are not valid characters. They may be reserved, private, or other. More info at: http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Noncharacters ## Examples iex> String.valid_character?("a") true iex> String.valid_character?("ø") true iex> String.valid_character?("\x{ffff}") false """ @spec valid_character?(t) :: boolean def valid_character?(<<_ :: utf8>> = codepoint), do: valid?(codepoint) def valid_character?(_), do: false @doc ~S""" Splits the string into chunks of characters that share a common trait. The trait can be one of two options: * `:valid` – the string is split into chunks of valid and invalid character sequences * `:printable` – the string is split into chunks of printable and non-printable character sequences Returns a list of binaries each of which contains only one kind of characters. If the given string is empty, an empty list is returned. ## Examples iex> String.chunk(<>, :valid) ["abc\0"] iex> String.chunk(<>, :valid) ["abc\0", <<0x0ffff::utf8>>] iex> String.chunk(<>, :printable) ["abc", <<0, 0x0ffff::utf8>>] """ @spec chunk(t, :valid | :printable) :: [t] def chunk(string, trait) def chunk("", _), do: [] def chunk(str, trait) when trait in [:valid, :printable] do {cp, _} = next_codepoint(str) pred_fn = make_chunk_pred(trait) do_chunk(str, pred_fn.(cp), pred_fn) end defp do_chunk(str, flag, pred_fn), do: do_chunk(str, [], <<>>, flag, pred_fn) defp do_chunk(<<>>, acc, <<>>, _, _), do: Enum.reverse(acc) defp do_chunk(<<>>, acc, chunk, _, _), do: Enum.reverse(acc, [chunk]) defp do_chunk(str, acc, chunk, flag, pred_fn) do {cp, rest} = next_codepoint(str) if pred_fn.(cp) != flag do do_chunk(rest, [chunk|acc], cp, not flag, pred_fn) else do_chunk(rest, acc, chunk <> cp, flag, pred_fn) end end defp make_chunk_pred(:valid), do: &valid?/1 defp make_chunk_pred(:printable), do: &printable?/1 @doc """ Returns Unicode graphemes in the string as per Extended Grapheme Cluster algorithm outlined in the [Unicode Standard Annex #29, Unicode Text Segmentation](http://www.unicode.org/reports/tr29/). ## Examples iex> String.graphemes("Ńaïve") ["Ń", "a", "ï", "v", "e"] """ @spec graphemes(t) :: [grapheme] defdelegate graphemes(string), to: String.Graphemes @doc """ Returns the next grapheme in a String. The result is a tuple with the grapheme and the remainder of the string or `nil` in case the String reached its end. ## Examples iex> String.next_grapheme("olá") {"o", "lá"} """ @compile {:inline, next_grapheme: 1} @spec next_grapheme(t) :: {grapheme, t} | nil defdelegate next_grapheme(string), to: String.Graphemes @doc """ Returns the first grapheme from a utf8 string, `nil` if the string is empty. ## Examples iex> String.first("elixir") "e" iex> String.first("եոգլի") "ե" """ @spec first(t) :: grapheme | nil def first(string) do case next_grapheme(string) do {char, _} -> char nil -> nil end end @doc """ Returns the last grapheme from a utf8 string, `nil` if the string is empty. ## Examples iex> String.last("elixir") "r" iex> String.last("եոգլի") "ի" """ @spec last(t) :: grapheme | nil def last(string) do do_last(next_grapheme(string), nil) end defp do_last({char, rest}, _) do do_last(next_grapheme(rest), char) end defp do_last(nil, last_char), do: last_char @doc """ Returns the number of Unicode graphemes in a utf8 string. ## Examples iex> String.length("elixir") 6 iex> String.length("եոգլի") 5 """ @spec length(t) :: non_neg_integer def length(string) do do_length(next_grapheme(string)) end defp do_length({_, rest}) do 1 + do_length(next_grapheme(rest)) end defp do_length(nil), do: 0 @doc """ Returns the grapheme in the `position` of the given utf8 `string`. If `position` is greater than `string` length, then it returns `nil`. ## Examples iex> String.at("elixir", 0) "e" iex> String.at("elixir", 1) "l" iex> String.at("elixir", 10) nil iex> String.at("elixir", -1) "r" iex> String.at("elixir", -10) nil """ @spec at(t, integer) :: grapheme | nil def at(string, position) when is_integer(position) and position >= 0 do do_at(next_grapheme(string), position, 0) end def at(string, position) when is_integer(position) and position < 0 do real_pos = length(string) - abs(position) case real_pos >= 0 do true -> do_at(next_grapheme(string), real_pos, 0) false -> nil end end defp do_at({_, rest}, desired_pos, current_pos) when desired_pos > current_pos do do_at(next_grapheme(rest), desired_pos, current_pos + 1) end defp do_at({char, _}, desired_pos, desired_pos) do char end defp do_at(nil, _, _), do: nil @doc """ Returns a substring starting at the offset `start`, and of length `len`. If the offset is greater than string length, then it returns `""`. Remember this function works with Unicode codepoints and considers the slices to represent codepoint offsets. If you want to split on raw bytes, check `Kernel.binary_part/3` instead. ## Examples iex> String.slice("elixir", 1, 3) "lix" iex> String.slice("elixir", 1, 10) "lixir" iex> String.slice("elixir", 10, 3) "" iex> String.slice("elixir", -4, 4) "ixir" iex> String.slice("elixir", -10, 3) "" iex> String.slice("a", 0, 1500) "a" iex> String.slice("a", 1, 1500) "" iex> String.slice("a", 2, 1500) "" """ @spec slice(t, integer, integer) :: grapheme def slice(_, _, 0) do "" end def slice(string, start, len) when start >= 0 and len >= 0 do case do_count_bytes(next_grapheme(string), start, 0) do {nil, _} -> "" {next, start_bytes} -> {_, len_bytes} = do_count_bytes(next, len, 0) binary_part(string, start_bytes, len_bytes) end end def slice(string, start, len) when start < 0 and len >= 0 do start = length(string) + start case start >= 0 do true -> slice(string, start, len) false -> "" end end defp do_count_bytes(next, 0, acc), do: {next, acc} defp do_count_bytes(nil, _, acc), do: {nil, acc} defp do_count_bytes({char, rest}, counter, acc) do do_count_bytes(next_grapheme(rest), counter - 1, acc + byte_size(char)) end @doc """ Returns a substring from the offset given by the start of the range to the offset given by the end of the range. If the start of the range is not a valid offset for the given string or if the range is in reverse order, returns `""`. If the start or end of the range is negative, the whole string is traversed first in order to convert the negative indices into positive ones. Remember this function works with Unicode codepoints and considers the slices to represent codepoints offsets. If you want to split on raw bytes, check `Kernel.binary_part/3` instead. ## Examples iex> String.slice("elixir", 1..3) "lix" iex> String.slice("elixir", 1..10) "lixir" iex> String.slice("elixir", 10..3) "" iex> String.slice("elixir", -4..-1) "ixir" iex> String.slice("elixir", 2..-1) "ixir" iex> String.slice("elixir", -4..6) "ixir" iex> String.slice("elixir", -1..-4) "" iex> String.slice("elixir", -10..-7) "" iex> String.slice("a", 0..1500) "a" iex> String.slice("a", 1..1500) "" """ @spec slice(t, Range.t) :: t def slice(string, range) def slice("", _.._), do: "" def slice(string, first..-1) when first >= 0 do case do_count_bytes(next_grapheme(string), first, 0) do {nil, _} -> "" {_, start_bytes} -> binary_part(string, start_bytes, byte_size(string) - start_bytes) end end def slice(string, first..last) when first >= 0 and last >= 0 do if last >= first do slice(string, first, last - first + 1) else "" end end def slice(string, first..last) do {bytes, length} = do_acc_bytes(next_grapheme(string), [], 0) if first < 0, do: first = length + first if last < 0, do: last = length + last if first < 0 or first > last or first > length do "" else last = min(last + 1, length) bytes = Enum.drop(bytes, length - last) first = last - first {length_bytes, start_bytes} = Enum.split(bytes, first) binary_part(string, Enum.sum(start_bytes), Enum.sum(length_bytes)) end end defp do_acc_bytes({char, rest}, bytes, length) do do_acc_bytes(next_grapheme(rest), [byte_size(char)|bytes], length + 1) end defp do_acc_bytes(nil, bytes, length) do {bytes, length} end @doc """ Returns `true` if `string` starts with any of the prefixes given, otherwise returns `false`. `prefixes` can be either a single prefix or a list of prefixes. ## Examples iex> String.starts_with? "elixir", "eli" true iex> String.starts_with? "elixir", ["erlang", "elixir"] true iex> String.starts_with? "elixir", ["erlang", "ruby"] false """ @spec starts_with?(t, t | [t]) :: boolean def starts_with?(_string, "") do IO.puts :stderr, "[deprecation] Calling String.starts_with?/2 with an empty string is deprecated and " <> "will fail in the future\n" <> Exception.format_stacktrace() true end def starts_with?(_string, []) do false end def starts_with?(string, prefix) when is_list(prefix) or is_binary(prefix) do Kernel.match?({0, _}, :binary.match(string, prefix)) end @doc """ Returns `true` if `string` ends with any of the suffixes given, otherwise returns `false`. `suffixes` can be either a single suffix or a list of suffixes. ## Examples iex> String.ends_with? "language", "age" true iex> String.ends_with? "language", ["youth", "age"] true iex> String.ends_with? "language", ["youth", "elixir"] false """ @spec ends_with?(t, t | [t]) :: boolean def ends_with?(_string, "") do IO.puts :stderr, "[deprecation] Calling String.ends_with?/2 with an empty string is deprecated and " <> "will fail in the future\n" <> Exception.format_stacktrace() true end def ends_with?(string, suffixes) when is_list(suffixes) do Enum.any?(suffixes, &do_ends_with(string, &1)) end def ends_with?(string, suffix) do do_ends_with(string, suffix) end defp do_ends_with(string, suffix) when is_binary(suffix) do string_size = byte_size(string) suffix_size = byte_size(suffix) scope = {string_size - suffix_size, suffix_size} (suffix_size <= string_size) and (:nomatch != :binary.match(string, suffix, [scope: scope])) end @doc """ Checks if `string` matches the given regular expression. ## Examples iex> String.match?("foo", ~r/foo/) true iex> String.match?("bar", ~r/foo/) false """ @spec match?(t, Regex.t) :: boolean def match?(string, regex) do Regex.match?(regex, string) end @doc """ Checks if `string` contains any of the given `contents`. `contents` can be either a single string or a list of strings. ## Examples iex> String.contains? "elixir of life", "of" true iex> String.contains? "elixir of life", ["life", "death"] true iex> String.contains? "elixir of life", ["death", "mercury"] false The argument can also be a precompiled pattern: iex> pattern = :binary.compile_pattern(["life", "death"]) iex> String.contains? "elixir of life", pattern true """ @spec contains?(t, pattern) :: boolean def contains?(_string, "") do IO.puts :stderr, "[deprecation] Calling String.contains?/2 with an empty string is deprecated and " <> "will fail in the future\n" <> Exception.format_stacktrace() true end def contains?(_string, []) do false end def contains?(string, contents) do :binary.match(string, contents) != :nomatch end @doc """ Converts a string into a char list. Specifically, this functions takes a UTF-8 encoded binary and returns a list of its integer codepoints. It is similar to `codepoints/1` except that the latter returns a list of codepoints as strings. In case you need to work with bytes, take a look at the [`:binary` module](http://erlang.org/doc/man/binary.html). ## Examples iex> String.to_char_list("æß") 'æß' """ @spec to_char_list(t) :: char_list def to_char_list(string) when is_binary(string) do case :unicode.characters_to_list(string) do result when is_list(result) -> result {:error, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :invalid {:incomplete, encoded, rest} -> raise UnicodeConversionError, encoded: encoded, rest: rest, kind: :incomplete end end @doc """ Converts a string to an atom. Currently Elixir does not support the conversion of strings that contain Unicode codepoints greater than 0xFF. Inlined by the compiler. ## Examples iex> String.to_atom("my_atom") :my_atom """ @spec to_atom(String.t) :: atom def to_atom(string) do :erlang.binary_to_atom(string, :utf8) end @doc """ Converts a string to an existing atom. Currently Elixir does not support the conversion of strings that contain Unicode codepoints greater than 0xFF. Inlined by the compiler. ## Examples iex> :my_atom iex> String.to_existing_atom("my_atom") :my_atom iex> String.to_existing_atom("this_atom_will_never_exist") ** (ArgumentError) argument error """ @spec to_existing_atom(String.t) :: atom def to_existing_atom(string) do :erlang.binary_to_existing_atom(string, :utf8) end @doc """ Returns an integer whose text representation is `string`. Inlined by the compiler. ## Examples iex> String.to_integer("123") 123 """ @spec to_integer(String.t) :: integer def to_integer(string) do :erlang.binary_to_integer(string) end @doc """ Returns an integer whose text representation is `string` in base `base`. Inlined by the compiler. ## Examples iex> String.to_integer("3FF", 16) 1023 """ @spec to_integer(String.t, 2..36) :: integer def to_integer(string, base) do :erlang.binary_to_integer(string, base) end @doc """ Returns a float whose text representation is `string`. `string` must be the string representation of a float. If a string representation of an integer wants to be used, then `Float.parse/1` should be used instead, otherwise an argument error will be raised. Inlined by the compiler. ## Examples iex> String.to_float("2.2017764e+0") 2.2017764 iex> String.to_float("3.0") 3.0 """ @spec to_float(String.t) :: float def to_float(string) do :erlang.binary_to_float(string) end @doc """ Returns a float value between 0 (equates to no similarity) and 1 (is an exact match) representing [Jaro](http://en.wikipedia.org/wiki/Jaro–Winkler_distance) distance between `str1` and `str2`. The Jaro distance metric is designed and best suited for short strings such as person names. ## Examples iex> String.jaro_distance("dwayne", "duane") 0.8222222222222223 iex> String.jaro_distance("even", "odd") 0.0 """ @spec jaro_distance(t, t) :: 0..1 def jaro_distance(str1, str2) def jaro_distance(str, str), do: 1.0 def jaro_distance(_str, ""), do: 0.0 def jaro_distance("", _str), do: 0.0 def jaro_distance(str1, str2) do {chars1, len1} = decompose(str1) {chars2, len2} = decompose(str2) case match(chars1, len1, chars2, len2) do {0, _trans} -> 0.0 {comm, trans} -> ((comm / len1) + (comm / len2) + ((comm - trans) / comm)) / 3 end end @compile {:inline, decompose: 1} defp decompose(str) do chars = graphemes(str) {chars, Kernel.length(chars)} end defp match(chars1, len1, chars2, len2) do if len1 < len2 do match(chars1, chars2, div(len2, 2) - 1) else match(chars2, chars1, div(len1, 2) - 1) end end defp match(chars1, chars2, lim) do match(chars1, chars2, {0, lim}, {0, 0, -1}, 0) end defp match([char | rest], chars, range, state, idx) do {chars, state} = submatch(char, chars, range, state, idx) case range do {lim, lim} -> match(rest, tl(chars), range, state, idx + 1) {pre, lim} -> match(rest, chars, {pre + 1, lim}, state, idx + 1) end end defp match([], _, _, {comm, trans, _}, _), do: {comm, trans} defp submatch(char, chars, {pre, _} = range, state, idx) do case detect(char, chars, range) do nil -> {chars, state} {subidx, chars} -> {chars, proceed(state, idx - pre + subidx)} end end defp detect(char, chars, {pre, lim}) do detect(char, chars, pre + 1 + lim, 0, []) end defp detect(_char, _chars, 0, _idx, _acc), do: nil defp detect(_char, [], _lim, _idx, _acc), do: nil defp detect(char, [char | rest], _lim, idx, acc), do: {idx, Enum.reverse(acc, [nil | rest])} defp detect(char, [other | rest], lim, idx, acc), do: detect(char, rest, lim - 1, idx + 1, [other | acc]) defp proceed({comm, trans, former}, current) do if current < former do {comm + 1, trans + 1, current} else {comm + 1, trans, current} end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/string/000077500000000000000000000000001254730255300212335ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/string/chars.ex000066400000000000000000000024361254730255300226760ustar00rootroot00000000000000import Kernel, except: [to_string: 1] defprotocol String.Chars do @moduledoc ~S""" The String.Chars protocol is responsible for converting a structure to a Binary (only if applicable). The only function required to be implemented is `to_string` which does the conversion. The `to_string` function automatically imported by Kernel invokes this protocol. String interpolation also invokes to_string in its arguments. For example, `"foo#{bar}"` is the same as `"foo" <> to_string(bar)`. """ def to_string(thing) end defimpl String.Chars, for: Atom do def to_string(nil) do "" end def to_string(atom) do Atom.to_string(atom) end end defimpl String.Chars, for: BitString do def to_string(thing) when is_binary(thing) do thing end def to_string(thing) do raise Protocol.UndefinedError, protocol: @protocol, value: thing, description: "cannot convert a bitstring to a string" end end defimpl String.Chars, for: List do def to_string(char_list), do: List.to_string(char_list) end defimpl String.Chars, for: Integer do def to_string(thing) do Integer.to_string(thing) end end defimpl String.Chars, for: Float do def to_string(thing) do IO.iodata_to_binary(:io_lib_format.fwrite_g(thing)) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/string_io.ex000066400000000000000000000215271254730255300222670ustar00rootroot00000000000000defmodule StringIO do @moduledoc """ This module provides an IO device that wraps a string. ## Examples iex> {:ok, pid} = StringIO.open("foo") iex> IO.read(pid, 2) "fo" """ use GenServer @doc """ Creates an IO device. If the `:capture_prompt` option is set to `true`, prompts (specified as arguments to `IO.get*` functions) are captured. ## Examples iex> {:ok, pid} = StringIO.open("foo") iex> IO.gets(pid, ">") "foo" iex> StringIO.contents(pid) {"", ""} iex> {:ok, pid} = StringIO.open("foo", capture_prompt: true) iex> IO.gets(pid, ">") "foo" iex> StringIO.contents(pid) {"", ">"} """ @spec open(binary, Keyword.t) :: {:ok, pid} def open(string, options \\ []) when is_binary(string) do GenServer.start_link(__MODULE__, {string, options}, []) end @doc """ Returns current buffers. ## Examples iex> {:ok, pid} = StringIO.open("in") iex> IO.write(pid, "out") iex> StringIO.contents(pid) {"in", "out"} """ @spec contents(pid) :: {binary, binary} def contents(pid) when is_pid(pid) do GenServer.call(pid, :contents) end @doc """ Flushes output buffer. ## Examples iex> {:ok, pid} = StringIO.open("in") iex> IO.write(pid, "out") iex> StringIO.flush(pid) "out" iex> StringIO.contents(pid) {"in", ""} """ @spec flush(pid) :: binary def flush(pid) when is_pid(pid) do GenServer.call(pid, :flush) end @doc """ Stops the IO device and returns remaining buffers. ## Examples iex> {:ok, pid} = StringIO.open("in") iex> IO.write(pid, "out") iex> StringIO.close(pid) {:ok, {"in", "out"}} """ @spec close(pid) :: {:ok, {binary, binary}} def close(pid) when is_pid(pid) do GenServer.call(pid, :close) end ## callbacks def init({string, options}) do capture_prompt = options[:capture_prompt] || false {:ok, %{input: string, output: "", capture_prompt: capture_prompt}} end def handle_info({:io_request, from, reply_as, req}, s) do s = io_request(from, reply_as, req, s) {:noreply, s} end def handle_info(msg, s) do super(msg, s) end def handle_call(:contents, _from, %{input: input, output: output} = s) do {:reply, {input, output}, s} end def handle_call(:flush, _from, %{output: output} = s) do {:reply, output, %{s | output: ""}} end def handle_call(:close, _from, %{input: input, output: output} = s) do {:stop, :normal, {:ok, {input, output}}, s} end def handle_call(request, from, s) do super(request, from, s) end defp io_request(from, reply_as, req, s) do {reply, s} = io_request(req, s) io_reply(from, reply_as, to_reply(reply)) s end defp io_request({:put_chars, chars}, %{output: output} = s) do {:ok, %{s | output: << output :: binary, IO.chardata_to_string(chars) :: binary >>}} end defp io_request({:put_chars, m, f, as}, %{output: output} = s) do chars = apply(m, f, as) {:ok, %{s | output: << output :: binary, IO.chardata_to_string(chars) :: binary >>}} end defp io_request({:put_chars, _encoding, chars}, s) do io_request({:put_chars, chars}, s) end defp io_request({:put_chars, _encoding, mod, func, args}, s) do io_request({:put_chars, mod, func, args}, s) end defp io_request({:get_chars, prompt, n}, s) when n >= 0 do io_request({:get_chars, :latin1, prompt, n}, s) end defp io_request({:get_chars, encoding, prompt, n}, s) when n >= 0 do get_chars(encoding, prompt, n, s) end defp io_request({:get_line, prompt}, s) do io_request({:get_line, :latin1, prompt}, s) end defp io_request({:get_line, encoding, prompt}, s) do get_line(encoding, prompt, s) end defp io_request({:get_until, prompt, mod, fun, args}, s) do io_request({:get_until, :latin1, prompt, mod, fun, args}, s) end defp io_request({:get_until, encoding, prompt, mod, fun, args}, s) do get_until(encoding, prompt, mod, fun, args, s) end defp io_request({:get_password, encoding}, s) do get_line(encoding, "", s) end defp io_request({:setopts, _opts}, s) do {{:error, :enotsup}, s} end defp io_request(:getopts, s) do {{:ok, [binary: true, encoding: :unicode]}, s} end defp io_request({:get_geometry, :columns}, s) do {{:error, :enotsup}, s} end defp io_request({:get_geometry, :rows}, s) do {{:error, :enotsup}, s} end defp io_request({:requests, reqs}, s) do io_requests(reqs, {:ok, s}) end defp io_request(_, s) do {{:error, :request}, s} end ## get_chars defp get_chars(encoding, prompt, n, %{input: input, output: output, capture_prompt: capture_prompt} = s) do case do_get_chars(input, encoding, n) do {:error, _} = error -> {error, s} {result, input} -> if capture_prompt do output = << output :: binary, IO.chardata_to_string(prompt) :: binary >> end {result, %{s | input: input, output: output}} end end defp do_get_chars("", _encoding, _n) do {:eof, ""} end defp do_get_chars(input, :latin1, n) when byte_size(input) < n do {input, ""} end defp do_get_chars(input, :latin1, n) do <> = input {chars, rest} end defp do_get_chars(input, encoding, n) do try do case :file_io_server.count_and_find(input, n, encoding) do {buf_count, split_pos} when buf_count < n or split_pos == :none -> {input, ""} {_buf_count, split_pos} -> <> = input {chars, rest} end catch :exit, :invalid_unicode -> {:error, :invalid_unicode} end end ## get_line defp get_line(encoding, prompt, %{input: input, output: output, capture_prompt: capture_prompt} = s) do case :unicode.characters_to_list(input, encoding) do {:error, _, _} -> {{:error, :collect_line}, s} {:incomplete, _, _} -> {{:error, :collect_line}, s} chars -> {result, input} = do_get_line(chars, encoding) if capture_prompt do output = << output :: binary, IO.chardata_to_string(prompt) :: binary >> end {result, %{s | input: input, output: output}} end end defp do_get_line('', _encoding) do {:eof, ""} end defp do_get_line(chars, encoding) do {line, rest} = collect_line(chars) {:unicode.characters_to_binary(line, encoding), :unicode.characters_to_binary(rest, encoding)} end ## get_until defp get_until(encoding, prompt, mod, fun, args, %{input: input, output: output, capture_prompt: capture_prompt} = s) do case :unicode.characters_to_list(input, encoding) do {:error, _, _} -> {:error, s} {:incomplete, _, _} -> {:error, s} chars -> {result, input, count} = do_get_until(chars, encoding, mod, fun, args) if capture_prompt do output = << output :: binary, :binary.copy(IO.chardata_to_string(prompt), count) :: binary >> end input = case input do :eof -> "" _ -> :unicode.characters_to_binary(input, encoding) end {result, %{s | input: input, output: output}} end end defp do_get_until(chars, encoding, mod, fun, args, continuation \\ [], count \\ 0) defp do_get_until('', encoding, mod, fun, args, continuation, count) do case apply(mod, fun, [continuation, :eof | args]) do {:done, result, rest} -> {result, rest, count + 1} {:more, next_continuation} -> do_get_until('', encoding, mod, fun, args, next_continuation, count + 1) end end defp do_get_until(chars, encoding, mod, fun, args, continuation, count) do {line, rest} = collect_line(chars) case apply(mod, fun, [continuation, line | args]) do {:done, result, rest1} -> unless rest1 == :eof do rest = rest1 ++ rest end {result, rest, count + 1} {:more, next_continuation} -> do_get_until(rest, encoding, mod, fun, args, next_continuation, count + 1) end end ## io_requests defp io_requests([r|rs], {:ok, s}) do io_requests(rs, io_request(r, s)) end defp io_requests(_, result) do result end ## helpers defp collect_line(chars) do collect_line(chars, []) end defp collect_line([], stack) do {:lists.reverse(stack), []} end defp collect_line([?\r, ?\n | rest], stack) do {:lists.reverse([?\n|stack]), rest} end defp collect_line([?\n | rest], stack) do {:lists.reverse([?\n|stack]), rest} end defp collect_line([h|t], stack) do collect_line(t, [h|stack]) end defp io_reply(from, reply_as, reply) do send from, {:io_reply, reply_as, reply} end defp to_reply(list) when is_list(list), do: IO.chardata_to_string(list) defp to_reply(other), do: other end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/supervisor.ex000066400000000000000000000431361254730255300225130ustar00rootroot00000000000000defmodule Supervisor do @moduledoc """ A behaviour module for implementing supervision functionality. A supervisor is a process which supervises other processes called child processes. Supervisors are used to build a hierarchical process structure called a supervision tree, a nice way to structure fault-tolerant applications. A supervisor implemented using this module will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree. ## Example In order to define a supervisor, we need to first define a child process that is going to be supervised. In order to do so, we will define a GenServer that represents a stack: defmodule Stack do use GenServer def start_link(state, opts) do GenServer.start_link(__MODULE__, state, opts) end def handle_call(:pop, _from, [h|t]) do {:reply, h, t} end def handle_cast({:push, h}, t) do {:noreply, [h|t]} end end We can now define our supervisor and start it as follows: # Import helpers for defining supervisors import Supervisor.Spec # We are going to supervise the Stack server which # will be started with a single argument [:hello] # and the default name of :sup_stack. children = [ worker(Stack, [[:hello], [name: :sup_stack]]) ] # Start the supervisor with our one child {:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one) Notice that when starting the GenServer, we are registering it with name `:sup_stack`, which allows us to call it directly and get what is on the stack: GenServer.call(:sup_stack, :pop) #=> :hello GenServer.cast(:sup_stack, {:push, :world}) #=> :ok GenServer.call(:sup_stack, :pop) #=> :world However, there is a bug in our stack server. If we call `:pop` and the stack is empty, it is going to crash because no clause matches. Let's try it: GenServer.call(:sup_stack, :pop) ** (exit) exited in: GenServer.call(:sup_stack, :pop, 5000) Luckily, since the server is being supervised by a supervisor, the supervisor will automatically start a new one, with the default stack of `[:hello]` like before: GenServer.call(:sup_stack, :pop) == :hello Supervisors support different strategies; in the example above, we have chosen `:one_for_one`. Furthermore, each supervisor can have many workers and supervisors as children, each of them with their specific configuration, shutdown values, and restart strategies. Continue reading this moduledoc to learn more about supervision strategies and then follow to the `Supervisor.Spec` module documentation to learn about the specification for workers and supervisors. ## Module-based supervisors In the example above, a supervisor was dynamically created by passing the supervision structure to `start_link/2`. However, supervisors can also be created by explicitly defining a supervision module: defmodule MyApp.Supervisor do use Supervisor def start_link do Supervisor.start_link(__MODULE__, []) end def init([]) do children = [ worker(Stack, [[:hello]]) ] supervise(children, strategy: :one_for_one) end end You may want to use a module-based supervisor if: * You need to do some particular action on supervisor initialization, like setting up a ETS table. * You want to perform partial hot-code swapping of the tree. For example, if you add or remove children, the module-based supervision will add and remove the new children directly, while the dynamic supervision requires the whole tree to be restarted in order to perform such swaps. ## Strategies * `:one_for_one` - if a child process terminates, only that process is restarted. * `:one_for_all` - if a child process terminates, all other child processes are terminated and then all child processes (including the terminated one) are restarted. * `:rest_for_one` - if a child process terminates, the "rest" of the child processes, i.e. the child processes after the terminated one in start order, are terminated. Then the terminated child process and the rest of the child processes are restarted. * `:simple_one_for_one` - similar to `:one_for_one` but suits better when dynamically attaching children. This strategy requires the supervisor specification to contain only one child. Many functions in this module behave slightly differently when this strategy is used. ## Simple one for one The simple one for one supervisor is useful when you want to dynamically start and stop supervisor children. For example, imagine you want to dynamically create multiple stacks. We can do so by defining a simple one for one supervisor: # Import helpers for defining supervisors import Supervisor.Spec # This time, we don't pass any argument because # the argument will be given when we start the child children = [ worker(Stack, [], restart: :transient) ] # Start the supervisor with our one child {:ok, sup_pid} = Supervisor.start_link(children, strategy: :simple_one_for_one) There are a couple differences here: * The simple one for one specification can define only one child which works as a template for when we call `start_child/2` * We have define the child to have restart strategy of transient. This means that, if the child process exits due to a `:normal`, `:shutdown` or `{:shutdown, term}` reason, it won't be restarted. This is useful as it allows our workers to politely shutdown and be removed from the simple one for one supervisor, without being restarted. You can find more information about restart strategies on `Supervisor.Spec` With the supervisor defined, let's dynamically start stacks: {:ok, pid} = Supervisor.start_child(sup_pid, [[:hello, :world], []]) GenServer.call(pid, :pop) #=> :hello GenServer.call(pid, :pop) #=> :world {:ok, pid} = Supervisor.start_child(sup_pid, [[:something, :else], []]) GenServer.call(pid, :pop) #=> :something GenServer.call(pid, :pop) #=> :else Supervisor.count_children(sup_pid) #=> %{active: 2, specs: 1, supervisors: 0, workers: 2} ## Exit reasons From the example above, you may have noticed that the transient restart strategy for the worker does not restart the child in case it crashes with reason `:normal`, `:shutdown` or `{:shutdown, term}`. So one may ask: which exit reason should I choose when existing my worker? There are three options: * `:normal` - on such cases, the exit won't be logged, there is no restart on transient mode and linked processes do not exit * `:shutdown` or `{:shutdown, term}` - on such cases, the exit won't be logged, there is no restart on transient mode and linked processes exit with the same reason unless trapping exits * any other term - on such cases, the exit will be logged, there are restarts on transient mode and linked processes exit with the same reason unless trapping exits ## Name Registration A supervisor is bound to the same name registration rules as a `GenServer`. Read more about it in the `GenServer` docs. """ @doc false defmacro __using__(_) do quote location: :keep do @behaviour :supervisor import Supervisor.Spec end end @typedoc "Return values of `start_link` functions" @type on_start :: {:ok, pid} | :ignore | {:error, {:already_started, pid} | {:shutdown, term} | term} @typedoc "Return values of `start_child` functions" @type on_start_child :: {:ok, child} | {:ok, child, info :: term} | {:error, {:already_started, child} | :already_present | term} @type child :: pid | :undefined @typedoc "The Supervisor name" @type name :: atom | {:global, term} | {:via, module, term} @typedoc "Options used by the `start*` functions" @type options :: [name: name, strategy: Supervisor.Spec.strategy, max_restarts: non_neg_integer, max_seconds: non_neg_integer] @typedoc "The supervisor reference" @type supervisor :: pid | name | {atom, node} @doc """ Starts a supervisor with the given children. A strategy is required to be given as an option. Furthermore, the `:max_restarts` and `:max_seconds` value can be configured as described in `Supervisor.Spec.supervise/2` docs. The options can also be used to register a supervisor name. The supported values are described under the `Name Registration` section in the `GenServer` module docs. If the supervisor and its child processes are successfully created (i.e. if the start function of all child processes returns `{:ok, child}`, `{:ok, child, info}`, or `:ignore`) the function returns `{:ok, pid}`, where `pid` is the pid of the supervisor. If there already exists a process with the specified name, the function returns `{:error, {:already_started, pid}}`, where pid is the pid of that process. If any of the child process start functions fail or return an error tuple or an erroneous value, the supervisor will first terminate all already started child processes with reason `:shutdown` and then terminate itself and return `{:error, {:shutdown, reason}}`. Note that the `Supervisor` is linked to the parent process and will exit not only on crashes but also if the parent process exits with `:normal` reason. """ @spec start_link([tuple], options) :: on_start def start_link(children, options) when is_list(children) do spec = Supervisor.Spec.supervise(children, options) start_link(Supervisor.Default, spec, options) end @doc """ Starts a supervisor module with the given `arg`. To start the supervisor, the `init/1` callback will be invoked in the given module. The `init/1` callback must return a supervision specification which can be created with the help of `Supervisor.Spec` module. If the `init/1` callback returns `:ignore`, this function returns `:ignore` as well and the supervisor terminates with reason `:normal`. If it fails or returns an incorrect value, this function returns `{:error, term}` where `term` is a term with information about the error, and the supervisor terminates with reason `term`. The `:name` option can also be given in order to register a supervisor name, the supported values are described under the `Name Registration` section in the `GenServer` module docs. Other failure conditions are specified in `start_link/2` docs. """ @spec start_link(module, term, options) :: on_start def start_link(module, arg, options \\ []) when is_list(options) do case Keyword.get(options, :name) do nil -> :supervisor.start_link(module, arg) atom when is_atom(atom) -> :supervisor.start_link({:local, atom}, module, arg) other when is_tuple(other) -> :supervisor.start_link(other, module, arg) end end @doc """ Dynamically adds and starts a child specification to the supervisor. `child_spec` should be a valid child specification (unless the supervisor is a `:simple_one_for_one` supervisor, see below). The child process will be started as defined in the child specification. In the case of `:simple_one_for_one`, the child specification defined in the supervisor will be used and instead of a `child_spec`, an arbitrary list of terms is expected. The child process will then be started by appending the given list to the existing function arguments in the child specification. If a child specification with the specified id already exists, `child_spec` is discarded and the function returns an error with `:already_started` or `:already_present` if the corresponding child process is running or not. If the child process starts, function returns `{:ok, child}` or `{:ok, child, info}`, the child specification and pid is added to the supervisor and the function returns the same value. If the child process starts, function returns `:ignore`, the child specification is added to the supervisor, the pid is set to undefined and the function returns `{:ok, :undefined}`. If the child process starts, function returns an error tuple or an erroneous value, or if it fails, the child specification is discarded and the function returns `{:error, error}` where `error` is a term containing information about the error and child specification. """ @spec start_child(supervisor, Supervisor.Spec.spec | [term]) :: on_start_child def start_child(supervisor, child_spec_or_args) do call(supervisor, {:start_child, child_spec_or_args}) end @doc """ Terminates the given pid or child id. If the supervisor is not a `simple_one_for_one`, the child id is expected and the process, if there is one, is terminated; the child specification is kept unless the child is temporary. In case of a `simple_one_for_one` supervisor, a pid is expected. If the child specification identifier is given instead of a `pid`, the function will return `{:error, :simple_one_for_one}`. A non-temporary child process may later be restarted by the supervisor. The child process can also be restarted explicitly by calling `restart_child/2`. Use `delete_child/2` to remove the child specification. If successful, the function returns `:ok`. If there is no child specification or pid, the function returns `{:error, :not_found}`. """ @spec terminate_child(supervisor, pid | Supervisor.Spec.child_id) :: :ok | {:error, error} when error: :not_found | :simple_one_for_one def terminate_child(supervisor, pid_or_child_id) do call(supervisor, {:terminate_child, pid_or_child_id}) end @doc """ Deletes the child specification identified by `child_id`. The corresponding child process must not be running, use `terminate_child/2` to terminate it. If successful, the function returns `:ok`. This function may error with an appropriate error tuple if the `child_id` is not found, or if the current process is running or being restarted. This operation is not supported by `simple_one_for_one` supervisors. """ @spec delete_child(supervisor, Supervisor.Spec.child_id) :: :ok | {:error, error} when error: :not_found | :simple_one_for_one | :running | :restarting def delete_child(supervisor, child_id) do call(supervisor, {:delete_child, child_id}) end @doc """ Restarts a child process identified by `child_id`. The child specification must exist and the corresponding child process must not be running. Note that for temporary children, the child specification is automatically deleted when the child terminates, and thus it is not possible to restart such children. If the child process start function returns `{:ok, child}` or `{:ok, child, info}`, the pid is added to the supervisor and the function returns the same value. If the child process start function returns `:ignore`, the pid remains set to `:undefined` and the function returns `{:ok, :undefined}`. This function may error with an appropriate error tuple if the `child_id` is not found, or if the current process is running or being restarted. If the child process start function returns an error tuple or an erroneous value, or if it fails, the function returns `{:error, error}`. This operation is not supported by `simple_one_for_one` supervisors. """ @spec restart_child(supervisor, Supervisor.Spec.child_id) :: {:ok, child} | {:ok, child, term} | {:error, error} when error: :not_found | :simple_one_for_one | :running | :restarting | term def restart_child(supervisor, child_id) do call(supervisor, {:restart_child, child_id}) end @doc """ Returns a list with information about all children. Note that calling this function when supervising a large number of children under low memory conditions can cause an out of memory exception. This function returns a list of tuples containing: * `id` - as defined in the child specification or `:undefined` in the case of a `simple_one_for_one` supervisor * `child` - the pid of the corresponding child process, the atom `:restarting` if the process is about to be restarted, or `:undefined` if there is no such process * `type` - `:worker` or `:supervisor` as defined in the child specification * `modules` – as defined in the child specification """ @spec which_children(supervisor) :: [{Supervisor.Spec.child_id | :undefined, child | :restarting, Supervisor.Spec.worker, Supervisor.Spec.modules}] def which_children(supervisor) do call(supervisor, :which_children) end @doc """ Returns a map containing count values for the supervisor. The map contains the following keys: * `:specs` - the total count of children, dead or alive * `:active` - the count of all actively running child processes managed by this supervisor * `:supervisors` - the count of all supervisors whether or not the child process is still alive * `:workers` - the count of all workers, whether or not the child process is still alive """ @spec count_children(supervisor) :: %{specs: non_neg_integer, active: non_neg_integer, supervisors: non_neg_integer, workers: non_neg_integer} def count_children(supervisor) do call(supervisor, :count_children) |> :maps.from_list end @compile {:inline, call: 2} defp call(supervisor, req) do GenServer.call(supervisor, req, :infinity) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/supervisor/000077500000000000000000000000001254730255300221465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/supervisor/default.ex000066400000000000000000000003731254730255300241330ustar00rootroot00000000000000defmodule Supervisor.Default do @moduledoc false @behaviour :supervisor @doc """ Supervisor callback that simply returns the given args. This is the supervisor used by `Supervisor.start_link/2`. """ def init(args) do args end endelixir-lang-1.1.0~0.20150708/lib/elixir/lib/supervisor/spec.ex000066400000000000000000000175171254730255300234510ustar00rootroot00000000000000defmodule Supervisor.Spec do @moduledoc """ Convenience functions for defining a supervision specification. ## Example By using the functions in this module one can define a supervisor and start it with `Supervisor.start_link/2`: import Supervisor.Spec children = [ worker(MyWorker, [arg1, arg2, arg3]), supervisor(MySupervisor, [arg1]) ] Supervisor.start_link(children, strategy: :one_for_one) In many situations, it may be handy to define supervisors backed by a module: defmodule MySupervisor do use Supervisor def start_link(arg) do Supervisor.start_link(__MODULE__, arg) end def init(arg) do children = [ worker(MyWorker, [arg], restart: :temporary) ] supervise(children, strategy: :simple_one_for_one) end end Notice in this case we don't have to explicitly import `Supervisor.Spec` as `use Supervisor` automatically does so. Explicit supervisors as above are required when there is a need to: 1. Partially change the supervision tree during hot-code swaps. 2. Define supervisors inside other supervisors. 3. Perform actions inside the supervision `init/1` callback. For example, you may want to start an ETS table that is linked to the supervisor (i.e. if the supervision tree needs to be restarted, the ETS table must be restarted too). ## Supervisor and worker options In the example above, we have defined workers and supervisors and each accepts the following options: * `:id` - a name used to identify the child specification internally by the supervisor; defaults to the given module name * `:function` - the function to invoke on the child to start it * `:restart` - defines when the child process should restart * `:shutdown` - defines how a child process should be terminated * `:modules` - it should be a list with one element `[module]`, where module is the name of the callback module only if the child process is a `Supervisor` or `GenServer`; if the child process is a `GenEvent`, modules should be `:dynamic` ### Restart values (:restart) The following restart values are supported: * `:permanent` - the child process is always restarted * `:temporary` - the child process is never restarted (not even when the supervisor's strategy is `:rest_for_one` or `:one_for_all`) * `:transient` - the child process is restarted only if it terminates abnormally, i.e. with another exit reason than `:normal`, `:shutdown` or `{:shutdown, term}` ### Shutdown values (:shutdown) The following shutdown values are supported: * `:brutal_kill` - the child process is unconditionally terminated using `exit(child, :kill)`. * `:infinity` - if the child process is a supervisor, it is a mechanism to give the subtree enough time to shutdown. It can also be used with workers with care. * Finally, it can also be any integer meaning that the supervisor tells the child process to terminate by calling `Process.exit(child, :shutdown)` and then waits for an exit signal back. If no exit signal is received within the specified time (in milliseconds), the child process is unconditionally terminated using `Process.exit(child, :kill)`. """ @typedoc "Supported strategies" @type strategy :: :simple_one_for_one | :one_for_one | :one_for_all | :rest_for_one @typedoc "Supported restart values" @type restart :: :permanent | :transient | :temporary @typedoc "Supported shutdown values" @type shutdown :: :brutal_kill | :infinity | non_neg_integer @typedoc "Supported worker values" @type worker :: :worker | :supervisor @typedoc "Supported module values" @type modules :: :dynamic | [module] @typedoc "Supported id values" @type child_id :: term @typedoc "The supervisor specification" @type spec :: {child_id, start_fun :: {module, atom, [term]}, restart, shutdown, worker, modules} @doc """ Receives a list of children (workers or supervisors) to supervise and a set of options. Returns a tuple containing the supervisor specification. ## Examples supervise children, strategy: :one_for_one ## Options * `:strategy` - the restart strategy option. It can be either `:one_for_one`, `:rest_for_one`, `:one_for_all`, or `:simple_one_for_one`. You can learn more about strategies in the `Supervisor` module docs. * `:max_restarts` - the maximum amount of restarts allowed in a time frame. Defaults to 3. * `:max_seconds` - the time frame in which `:max_restarts` applies. Defaults to 5. The `:strategy` option is required and by default maximum 3 restarts are allowed within 5 seconds. Please check the `Supervisor` module for a complete description of the available strategies. """ @spec supervise([spec], strategy: strategy, max_restarts: non_neg_integer, max_seconds: non_neg_integer) :: {:ok, tuple} def supervise(children, options) do unless strategy = options[:strategy] do raise ArgumentError, "expected :strategy option to be given" end maxR = Keyword.get(options, :max_restarts, 3) maxS = Keyword.get(options, :max_seconds, 5) assert_unique_ids(Enum.map(children, &elem(&1, 0))) {:ok, {{strategy, maxR, maxS}, children}} end defp assert_unique_ids([id|rest]) do if id in rest do raise ArgumentError, "duplicated id #{inspect id} found in the supervisor specification, " <> "please explicitly pass the :id option when defining this worker/supervisor" else assert_unique_ids(rest) end end defp assert_unique_ids([]) do :ok end @doc """ Defines the given `module` as a worker which will be started with the given arguments. worker ExUnit.Runner, [], restart: :permanent By default, the function `start_link` is invoked on the given module. Overall, the default values for the options are: [id: module, function: :start_link, restart: :permanent, shutdown: 5000, modules: [module]] Check `Supervisor.Spec` module docs for more information on the options. """ @spec worker(module, [term], [restart: restart, shutdown: shutdown, id: term, function: atom, modules: modules]) :: spec def worker(module, args, options \\ []) do child(:worker, module, args, options) end @doc """ Defines the given `module` as a supervisor which will be started with the given arguments. supervisor ExUnit.Runner, [], restart: :permanent By default, the function `start_link` is invoked on the given module. Overall, the default values for the options are: [id: module, function: :start_link, restart: :permanent, shutdown: :infinity, modules: [module]] Check `Supervisor.Spec` module docs for more information on the options. """ @spec supervisor(module, [term], [restart: restart, shutdown: shutdown, id: term, function: atom, modules: modules]) :: spec def supervisor(module, args, options \\ []) do options = Keyword.put_new(options, :shutdown, :infinity) child(:supervisor, module, args, options) end defp child(type, module, args, options) do id = Keyword.get(options, :id, module) modules = Keyword.get(options, :modules, modules(module)) function = Keyword.get(options, :function, :start_link) restart = Keyword.get(options, :restart, :permanent) shutdown = Keyword.get(options, :shutdown, 5000) {id, {module, function, args}, restart, shutdown, type, modules} end defp modules(GenEvent), do: :dynamic defp modules(module), do: [module] end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/system.ex000066400000000000000000000335671254730255300216250ustar00rootroot00000000000000defmodule System do @moduledoc """ The System module provides access to variables used or maintained by the VM and to functions that interact directly with the VM or the host system. """ defp strip_re(iodata, pattern) do :re.replace(iodata, pattern, "", [return: :binary]) end defp read_stripped(path) do case :file.read_file(path) do {:ok, binary} -> strip_re(binary, "^\s+|\s+$") _ -> "" end end # Read and strip the version from the `VERSION` file. defmacrop get_version do case read_stripped(:filename.join(__DIR__, "../../../VERSION")) do "" -> raise RuntimeError, message: "could not read the version number from VERSION" data -> data end end # Tries to run `git describe --always --tags`. In the case of success returns # the most recent tag. If that is not available, tries to read the commit hash # from .git/HEAD. If that fails, returns an empty string. defmacrop get_describe do dirpath = :filename.join(__DIR__, "../../../.git") case :file.read_file_info(dirpath) do {:ok, _} -> if :os.find_executable('git') do data = :os.cmd('git describe --always --tags') strip_re(data, "\n") else read_stripped(:filename.join(".git", "HEAD")) end _ -> "" end end # Get the date at compilation time. defmacrop get_date do IO.iodata_to_binary :httpd_util.rfc1123_date end @doc """ Elixir version information. Returns Elixir's version as binary. """ @spec version() :: String.t def version, do: get_version @doc """ Elixir build information. Returns a keyword list with Elixir version, git tag info and compilation date. """ @spec build_info() :: map def build_info do %{version: version, tag: get_describe, date: get_date} end @doc """ Lists command line arguments. Returns the list of command line arguments passed to the program. """ @spec argv() :: [String.t] def argv do :elixir_config.get(:argv) end @doc """ Modifies command line arguments. Changes the list of command line arguments. Use it with caution, as it destroys any previous argv information. """ @spec argv([String.t]) :: :ok def argv(args) do :elixir_config.put(:argv, args) end @doc """ Current working directory. Returns the current working directory or `nil` if one is not available. """ def cwd do case :file.get_cwd do {:ok, base} -> IO.chardata_to_string(fix_drive_letter(base)) _ -> nil end end defp fix_drive_letter([l, ?:, ?/ | rest] = original) when l in ?A..?Z do case :os.type() do {:win32, _} -> [l+?a-?A, ?:, ?/ | rest] _ -> original end end defp fix_drive_letter(original), do: original @doc """ Current working directory, exception on error. Returns the current working directory or raises `RuntimeError`. """ def cwd! do cwd || raise RuntimeError, message: "could not get a current working directory, the current location is not accessible" end @doc """ User home directory. Returns the user home directory (platform independent). """ def user_home do :elixir_config.get(:home) end @doc """ User home directory, exception on error. Same as `user_home/0` but raises `RuntimeError` instead of returning `nil` if no user home is set. """ def user_home! do user_home || raise RuntimeError, message: "could not find the user home, please set the HOME environment variable" end @doc ~S""" Writable temporary directory. Returns a writable temporary directory. Searches for directories in the following order: 1. the directory named by the TMPDIR environment variable 2. the directory named by the TEMP environment variable 3. the directory named by the TMP environment variable 4. `C:\TMP` on Windows or `/tmp` on Unix 5. as a last resort, the current working directory Returns `nil` if none of the above are writable. """ def tmp_dir do write_env_tmp_dir('TMPDIR') || write_env_tmp_dir('TEMP') || write_env_tmp_dir('TMP') || write_tmp_dir('/tmp') || ((cwd = cwd()) && write_tmp_dir(cwd)) end @doc """ Writable temporary directory, exception on error. Same as `tmp_dir/0` but raises `RuntimeError` instead of returning `nil` if no temp dir is set. """ def tmp_dir! do tmp_dir || raise RuntimeError, message: "could not get a writable temporary directory, " <> "please set the TMPDIR environment variable" end defp write_env_tmp_dir(env) do case :os.getenv(env) do false -> nil tmp -> write_tmp_dir(tmp) end end defp write_tmp_dir(dir) do case File.stat(dir) do {:ok, stat} -> case {stat.type, stat.access} do {:directory, access} when access in [:read_write, :write] -> IO.chardata_to_string(dir) _ -> nil end {:error, _} -> nil end end @doc """ Registers a program exit handler function. Registers a function that will be invoked at the end of program execution. Useful for invoking a hook in "script" mode. The handler always executes in a different process from the one it was registered in. As a consequence, any resources managed by the calling process (ETS tables, open files, etc.) won't be available by the time the handler function is invoked. The function must receive the exit status code as an argument. """ def at_exit(fun) when is_function(fun, 1) do :elixir_config.update :at_exit, &[fun|&1] end @doc """ Locates an executable on the system. This function looks up an executable program given its name using the environment variable PATH on Unix and Windows. It also considers the proper executable extension for each OS, so for Windows it will try to lookup files with `.com`, `.cmd` or similar extensions. """ @spec find_executable(binary) :: binary | nil def find_executable(program) when is_binary(program) do case :os.find_executable(String.to_char_list(program)) do false -> nil other -> List.to_string(other) end end @doc """ System environment variables. Returns a list of all environment variables. Each variable is given as a `{name, value}` tuple where both `name` and `value` are strings. """ @spec get_env() :: %{String.t => String.t} def get_env do Enum.into(:os.getenv, %{}, fn var -> var = IO.chardata_to_string var [k, v] = String.split var, "=", parts: 2 {k, v} end) end @doc """ Environment variable value. Returns the value of the environment variable `varname` as a binary, or `nil` if the environment variable is undefined. """ @spec get_env(binary) :: binary | nil def get_env(varname) when is_binary(varname) do case :os.getenv(String.to_char_list(varname)) do false -> nil other -> List.to_string(other) end end @doc """ Erlang VM process identifier. Returns the process identifier of the current Erlang emulator in the format most commonly used by the operating system environment. See http://www.erlang.org/doc/man/os.html#getpid-0 for more info. """ @spec get_pid() :: binary def get_pid, do: IO.iodata_to_binary(:os.getpid) @doc """ Sets an environment variable value. Sets a new `value` for the environment variable `varname`. """ @spec put_env(binary, binary) :: :ok def put_env(varname, value) when is_binary(varname) and is_binary(value) do :os.putenv String.to_char_list(varname), String.to_char_list(value) :ok end @doc """ Sets multiple environment variables. Sets a new value for each environment variable corresponding to each key in `dict`. """ @spec put_env(Dict.t) :: :ok def put_env(dict) do Enum.each dict, fn {key, val} -> put_env key, val end end @doc """ Deletes an environment variable. Removes the variable `varname` from the environment. """ @spec delete_env(String.t) :: :ok def delete_env(varname) do :os.unsetenv(String.to_char_list(varname)) :ok end @doc """ Last exception stacktrace. Note that the Erlang VM (and therefore this function) does not return the current stacktrace but rather the stacktrace of the latest exception. Inlined by the compiler into `:erlang.get_stacktrace/0`. """ def stacktrace do :erlang.get_stacktrace end @doc """ Halts the Erlang runtime system. Halts the Erlang runtime system where the argument `status` must be a non-negative integer, the atom `:abort` or a binary. * If an integer, the runtime system exits with the integer value which is returned to the operating system. * If `:abort`, the runtime system aborts producing a core dump, if that is enabled in the operating system. * If a string, an erlang crash dump is produced with status as slogan, and then the runtime system exits with status code 1. Note that on many platforms, only the status codes 0-255 are supported by the operating system. For more information, check: http://www.erlang.org/doc/man/erlang.html#halt-1 ## Examples System.halt(0) System.halt(1) System.halt(:abort) """ @spec halt() :: no_return @spec halt(non_neg_integer | binary | :abort) :: no_return def halt(status \\ 0) def halt(status) when is_integer(status) or status == :abort do :erlang.halt(status) end def halt(status) when is_binary(status) do :erlang.halt(String.to_char_list(status)) end @doc ~S""" Executes the given `command` with `args`. `command` is expected to be an executable available in PATH unless an absolute path is given. `args` must be a list of strings which are not expanded in any way. For example, this means wildcard expansion will not happen unless `Path.wildcard/2` is used. On Windows though, wildcard expansion is up to the program. This function returns a tuple containing the collected result and the command exit status. ## Examples iex> System.cmd "echo", ["hello"] {"hello\n", 0} iex> System.cmd "echo", ["hello"], env: [{"MIX_ENV", "test"}] {"hello\n", 0} iex> System.cmd "echo", ["hello"], into: IO.stream(:stdio, :line) hello {%IO.Stream{}, 0} ## Options * `:into` - injects the result into the given collectable, defaults to `""` * `:cd` - the directory to run the command in * `:env` - an enumerable of tuples containing environment key-value as binary * `:arg0` - set the command arg0 * `:stderr_to_stdout` - redirects stderr to stdout when `true` * `:parallelism` - when `true`, the VM will schedule port tasks to improve parallelism in the system. If set to `false`, the VM will try to perform commands immediately, improving latency at the expense of parallelism. The default can be set on system startup by passing the "+spp" argument to `--erl`. ## Error reasons If invalid arguments are given, `ArgumentError` is raised by `System.cmd/3`. `System.cmd/3` also expects a strict set of options and will raise if unknown or invalid options are given. Furthermore, `System.cmd/3` may fail with one of the POSIX reasons detailed below: * `:system_limit` - all available ports in the Erlang emulator are in use * `:enomem` - there was not enough memory to create the port * `:eagain` - there are no more available operating system processes * `:enametoolong` - the external command given was too long * `:emfile` - there are no more available file descriptors (for the operating system process that the Erlang emulator runs in) * `:enfile` - the file table is full (for the entire operating system) * `:eacces` - the command does not point to an executable file * `:enoent` - the command does not point to an existing file ## Shell commands If you desire to execute a trusted command inside a shell, with pipes, redirecting and so on, please check [Erlang's :os.cmd/1 function](http://www.erlang.org/doc/man/os.html#cmd-1). """ @spec cmd(binary, [binary], Keyword.t) :: {Collectable.t, exit_status :: non_neg_integer} def cmd(command, args, opts \\ []) when is_binary(command) and is_list(args) do cmd = String.to_char_list(command) cmd = if Path.type(cmd) == :absolute do cmd else :os.find_executable(cmd) || :erlang.error(:enoent, [command, args, opts]) end {into, opts} = cmd_opts(opts, [:use_stdio, :exit_status, :binary, :hide, args: args], "") {initial, fun} = Collectable.into(into) do_cmd Port.open({:spawn_executable, cmd}, opts), initial, fun end defp do_cmd(port, acc, fun) do receive do {^port, {:data, data}} -> do_cmd(port, fun.(acc, {:cont, data}), fun) {^port, {:exit_status, status}} -> {fun.(acc, :done), status} end end defp cmd_opts([{:into, any}|t], opts, _into), do: cmd_opts(t, opts, any) defp cmd_opts([{:cd, bin}|t], opts, into) when is_binary(bin), do: cmd_opts(t, [{:cd, bin}|opts], into) defp cmd_opts([{:arg0, bin}|t], opts, into) when is_binary(bin), do: cmd_opts(t, [{:arg0, bin}|opts], into) defp cmd_opts([{:stderr_to_stdout, true}|t], opts, into), do: cmd_opts(t, [:stderr_to_stdout|opts], into) defp cmd_opts([{:stderr_to_stdout, false}|t], opts, into), do: cmd_opts(t, opts, into) defp cmd_opts([{:parallelism, bool}|t], opts, into) when is_boolean(bool), do: cmd_opts(t, [{:parallelism, bool}|opts], into) defp cmd_opts([{:env, enum}|t], opts, into), do: cmd_opts(t, [{:env, validate_env(enum)}|opts], into) defp cmd_opts([{key, val}|_], _opts, _into), do: raise(ArgumentError, "invalid option #{inspect key} with value #{inspect val}") defp cmd_opts([], opts, into), do: {into, opts} defp validate_env(enum) do Enum.map enum, fn {k, v} -> {String.to_char_list(k), String.to_char_list(v)} other -> raise ArgumentError, "invalid environment key-value #{inspect other}" end end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/task.ex000066400000000000000000000174221254730255300212330ustar00rootroot00000000000000defmodule Task do @moduledoc """ Conveniences for spawning and awaiting for tasks. Tasks are processes meant to execute one particular action throughout their life-cycle, often with little or no communication with other processes. The most common use case for tasks is to compute a value asynchronously: task = Task.async(fn -> do_some_work() end) res = do_some_other_work() res + Task.await(task) Tasks spawned with `async` can be awaited on by its caller process (and only its caller) as shown in the example above. They are implemented by spawning a process that sends a message to the caller once the given computation is performed. Besides `async/1` and `await/2`, tasks can also be started as part of supervision trees and dynamically spawned in remote nodes. We will explore all three scenarios next. ## async and await The most common way to spawn a task is with `Task.async/1`. A new process will be created, linked and monitored by the caller. Once the task action finishes, a message will be sent to the caller with the result. `Task.await/2` is used to read the message sent by the task. On `await`, Elixir will also setup a monitor to verify if the process exited for any abnormal reason (or in case exits are being trapped by the caller). ## Supervised tasks It is also possible to spawn a task inside a supervision tree with `start_link/1` and `start_link/3`: Task.start_link(fn -> IO.puts "ok" end) Such tasks can be mounted in your supervision tree as: import Supervisor.Spec children = [ worker(Task, [fn -> IO.puts "ok" end]) ] Since these tasks are supervised and not directly linked to the caller, they cannot be awaited on. Note `start_link/1`, unlike `async/1`, returns `{:ok, pid}` (which is the result expected by supervision trees). ## Supervision trees The `Task.Supervisor` module allows developers to start supervisors that dynamically supervise tasks: {:ok, pid} = Task.Supervisor.start_link() Task.Supervisor.async(pid, MyMod, :my_fun, [arg1, arg2, arg3]) `Task.Supervisor` also makes it possible to spawn tasks in remote nodes as long as the supervisor is registered locally or globally: # In the remote node Task.Supervisor.start_link(name: :tasks_sup) # In the client Task.Supervisor.async({:tasks_sup, :remote@local}, MyMod, :my_fun, [arg1, arg2, arg3]) `Task.Supervisor` is more often started in your supervision tree as: import Supervisor.Spec children = [ supervisor(Task.Supervisor, [[name: :tasks_sup]]) ] Note that, when working with distributed tasks, one should use the `async/3` API, that expects explicit module, function and arguments, instead of `async/1` that works with anonymous functions. That's because the anonymous function API expects the same module version to exist on all involved nodes. Check the `Agent` module documentation for more information on distributed processes, as the limitations described in the agents documentation apply to the whole ecosystem. Finally, check `Task.Supervisor` for other operations supported by the Task supervisor. """ @doc """ The Task struct. It contains two fields: * `:pid` - the process reference of the task process; it may be a pid or a tuple containing the process and node names * `:ref` - the task monitor reference """ defstruct pid: nil, ref: nil @type t :: %__MODULE__{} @doc """ Starts a task as part of a supervision tree. """ @spec start_link(fun) :: {:ok, pid} def start_link(fun) do start_link(:erlang, :apply, [fun, []]) end @doc """ Starts a task as part of a supervision tree. """ @spec start_link(module, atom, [term]) :: {:ok, pid} def start_link(mod, fun, args) do Task.Supervised.start_link(get_info(self), {mod, fun, args}) end @doc """ Starts a task. This is only used when the task is used for side-effects (i.e. no interest in its return result) and it should not be linked to the current process. """ @spec start(fun) :: {:ok, pid} def start(fun) do start(:erlang, :apply, [fun, []]) end @doc """ Starts a task. This is only used when the task is used for side-effects (i.e. no interest in its return result) and it should not be linked to the current process. """ @spec start(module, atom, [term]) :: {:ok, pid} def start(mod, fun, args) do Task.Supervised.start(get_info(self), {mod, fun, args}) end @doc """ Starts a task that can be awaited on. This function spawns a process that is linked to and monitored by the caller process. A `Task` struct is returned containing the relevant information. ## Task's message format The reply sent by the task will be in the format `{ref, msg}`, where `ref` is the monitoring reference held by the task. """ @spec async(fun) :: t def async(fun) do async(:erlang, :apply, [fun, []]) end @doc """ Starts a task that can be awaited on. Similar to `async/1`, but the task is specified by the given module, function and arguments. """ @spec async(module, atom, [term]) :: t def async(mod, fun, args) do mfa = {mod, fun, args} pid = :proc_lib.spawn_link(Task.Supervised, :async, [self, get_info(self), mfa]) ref = Process.monitor(pid) send(pid, {self(), ref}) %Task{pid: pid, ref: ref} end defp get_info(self) do {node(), case Process.info(self, :registered_name) do {:registered_name, []} -> self() {:registered_name, name} -> name end} end @doc """ Awaits a task reply. A timeout, in milliseconds, can be given with default value of `5000`. In case the task process dies, this function will exit with the same reason as the task. If the timeout is exceeded, `await` will exit, however, the task will continue to run. Use `Process.kill/2` to terminate it. """ @spec await(t, timeout) :: term | no_return def await(%Task{ref: ref}=task, timeout \\ 5000) do receive do {^ref, reply} -> Process.demonitor(ref, [:flush]) reply {:DOWN, ^ref, _, _, :noconnection} -> mfa = {__MODULE__, :await, [task, timeout]} exit({{:nodedown, node(task.pid)}, mfa}) {:DOWN, ^ref, _, _, reason} -> exit({reason, {__MODULE__, :await, [task, timeout]}}) after timeout -> Process.demonitor(ref, [:flush]) exit({:timeout, {__MODULE__, :await, [task, timeout]}}) end end @doc """ Receives a group of tasks and a message and finds a task that matches the given message. This function returns a tuple with the task and the returned value in case the message matches a task that exited with success, it raises in case the found task failed or `nil` if no task was found. This function is useful in situations where multiple tasks are spawned and their results are collected later on. For example, a `GenServer` can spawn tasks, store the tasks in a list and later use `Task.find/2` to see if incoming messages are from any of the tasks. """ @spec find([t], any) :: {term, t} | nil | no_return def find(tasks, msg) def find(tasks, {ref, reply}) when is_reference(ref) do Enum.find_value tasks, fn %Task{ref: task_ref} = t when ref == task_ref -> Process.demonitor(ref, [:flush]) {reply, t} %Task{} -> nil end end def find(tasks, {:DOWN, ref, _, _, reason} = msg) when is_reference(ref) do find = fn(%Task{ref: task_ref}) -> task_ref == ref end case Enum.find(tasks, find) do %Task{pid: pid} when reason == :noconnection -> exit({{:nodedown, node(pid)}, {__MODULE__, :find, [tasks, msg]}}) %Task{} -> exit({reason, {__MODULE__, :find, [tasks, msg]}}) nil -> nil end end def find(_tasks, _msg) do nil end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/task/000077500000000000000000000000001254730255300206675ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/lib/task/supervised.ex000066400000000000000000000077371254730255300234340ustar00rootroot00000000000000defmodule Task.Supervised do @moduledoc false def start(info, fun) do {:ok, :proc_lib.spawn(__MODULE__, :noreply, [info, fun])} end def start_link(info, fun) do {:ok, :proc_lib.spawn_link(__MODULE__, :noreply, [info, fun])} end def start_link(caller, info, fun) do :proc_lib.start_link(__MODULE__, :reply, [caller, info, fun]) end def async(caller, info, mfa) do initial_call(mfa) ref = receive do: ({^caller, ref} -> ref) send caller, {ref, do_apply(info, mfa)} end def reply(caller, info, mfa) do initial_call(mfa) :erlang.link(caller) :proc_lib.init_ack({:ok, self()}) ref = # There is a race condition on this operation when working across # node that manifests if a `Task.Supervisor.async/1` call is made # while the supervisor is busy spawning previous tasks. # # Imagine the following workflow: # # 1. The nodes disconnect # 2. The async call fails and is caught, the calling process does not exit # 3. The task is spawned and links to the calling process, causing the nodes to reconnect # 4. The calling process has not exited and so does not send its monitor reference # 5. The spawned task waits forever for the monitor reference so it can begin # # We have solved this by specifying a timeout of 5000 seconds. # Given no work is done in the client between the task start and # sending the reference, 5000 should be enough to not raise false # negatives unless the nodes are indeed not available. receive do {^caller, ref} -> ref after 5000 -> exit(:timeout) end send caller, {ref, do_apply(info, mfa)} end def noreply(info, mfa) do initial_call(mfa) do_apply(info, mfa) end defp initial_call(mfa) do Process.put(:"$initial_call", get_initial_call(mfa)) end defp get_initial_call({:erlang, :apply, [fun, []]}) when is_function(fun, 0) do {:module, module} = :erlang.fun_info(fun, :module) {:name, name} = :erlang.fun_info(fun, :name) {module, name, 0} end defp get_initial_call({mod, fun, args}) do {mod, fun, length(args)} end defp do_apply(info, {module, fun, args} = mfa) do try do apply(module, fun, args) catch :error, value -> reason = {value, System.stacktrace()} exit(info, mfa, reason, reason) :throw, value -> reason = {{:nocatch, value}, System.stacktrace()} exit(info, mfa, reason, reason) :exit, value -> exit(info, mfa, {value, System.stacktrace()}, value) end end defp exit(_info, _mfa, _log_reason, reason) when reason == :normal when reason == :shutdown when tuple_size(reason) == 2 and elem(reason, 0) == :shutdown do exit(reason) end defp exit(info, mfa, log_reason, reason) do {fun, args} = get_running(mfa) :error_logger.format( '** Task ~p terminating~n' ++ '** Started from ~p~n' ++ '** When function == ~p~n' ++ '** arguments == ~p~n' ++ '** Reason for termination == ~n' ++ '** ~p~n', [self, get_from(info), fun, args, get_reason(log_reason)]) exit(reason) end defp get_from({node, pid_or_name}) when node == node(), do: pid_or_name defp get_from(other), do: other defp get_running({:erlang, :apply, [fun, []]}) when is_function(fun, 0), do: {fun, []} defp get_running({mod, fun, args}), do: {:erlang.make_fun(mod, fun, length(args)), args} defp get_reason({:undef, [{mod, fun, args, _info} | _] = stacktrace} = reason) when is_atom(mod) and is_atom(fun) do cond do :code.is_loaded(mod) === false -> {:"module could not be loaded", stacktrace} is_list(args) and not function_exported?(mod, fun, length(args)) -> {:"function not exported", stacktrace} is_integer(args) and not function_exported?(mod, fun, args) -> {:"function not exported", stacktrace} true -> reason end end defp get_reason(reason) do reason end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/task/supervisor.ex000066400000000000000000000077561254730255300234650ustar00rootroot00000000000000defmodule Task.Supervisor do @moduledoc """ A tasks supervisor. This module defines a supervisor which can be used to dynamically supervise tasks. Behind the scenes, this module is implemented as a `:simple_one_for_one` supervisor where the workers are temporary (i.e. they are not restarted after they die). The functions in this module allow tasks to be spawned and awaited from a supervisor, similar to the functions defined in the `Task` module. ## Name Registration A `Task.Supervisor` is bound to the same name registration rules as a `GenServer`. Read more about it in the `GenServer` docs. """ @doc """ Starts a new supervisor. The supported options are: * `:name` - used to register a supervisor name, the supported values are described under the `Name Registration` section in the `GenServer` module docs; * `:restart` - the restart strategy, may be `:temporary` (the default), `:transient` or `:permanent`. Check `Supervisor.Spec` for more info. Defaults to temporary as most tasks can't be effectively restarted after a crash; * `:shutdown` - `:brutal_kill` if the tasks must be killed directly on shutdown or an integer indicating the timeout value, defaults to 5000 milliseconds; * `:max_restarts` and `:max_seconds` - as specified in `Supervisor.Spec.supervise/2`; """ @spec start_link(Supervisor.options) :: Supervisor.on_start def start_link(opts \\ []) do import Supervisor.Spec {restart, opts} = Keyword.pop(opts, :restart, :temporary) {shutdown, opts} = Keyword.pop(opts, :shutdown, 5000) children = [worker(Task.Supervised, [], restart: restart, shutdown: shutdown)] Supervisor.start_link(children, [strategy: :simple_one_for_one] ++ opts) end @doc """ Starts a task that can be awaited on. The `supervisor` must be a reference as defined in `Task.Supervisor`. For more information on tasks, check the `Task` module. """ @spec async(Supervisor.supervisor, fun) :: Task.t def async(supervisor, fun) do async(supervisor, :erlang, :apply, [fun, []]) end @doc """ Starts a task that can be awaited on. The `supervisor` must be a reference as defined in `Task.Supervisor`. For more information on tasks, check the `Task` module. """ @spec async(Supervisor.supervisor, module, atom, [term]) :: Task.t def async(supervisor, module, fun, args) do args = [self, get_info(self), {module, fun, args}] {:ok, pid} = Supervisor.start_child(supervisor, args) ref = Process.monitor(pid) send pid, {self(), ref} %Task{pid: pid, ref: ref} end @doc """ Terminates the child with the given `pid`. """ @spec terminate_child(Supervisor.supervisor, pid) :: :ok def terminate_child(supervisor, pid) when is_pid(pid) do :supervisor.terminate_child(supervisor, pid) end @doc """ Returns all children pids. """ @spec children(Supervisor.supervisor) :: [pid] def children(supervisor) do :supervisor.which_children(supervisor) |> Enum.map(&elem(&1, 1)) end @doc """ Starts a task as child of the given `supervisor`. Note that the spawned process is not linked to the caller, but only to the supervisor. This command is useful in case the task needs to perform side-effects (like I/O) and does not need to report back to the caller. """ @spec start_child(Supervisor.supervisor, fun) :: {:ok, pid} def start_child(supervisor, fun) do start_child(supervisor, :erlang, :apply, [fun, []]) end @doc """ Starts a task as child of the given `supervisor`. Similar to `start_child/2` except the task is specified by the given `module`, `fun` and `args`. """ @spec start_child(Supervisor.supervisor, module, atom, [term]) :: {:ok, pid} def start_child(supervisor, module, fun, args) do Supervisor.start_child(supervisor, [get_info(self), {module, fun, args}]) end defp get_info(self) do {node(), case Process.info(self, :registered_name) do {:registered_name, []} -> self() {:registered_name, name} -> name end} end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/tuple.ex000066400000000000000000000044671254730255300214270ustar00rootroot00000000000000defmodule Tuple do @moduledoc """ Functions for working with tuples. See also `Kernel.elem/2`, `Kernel.is_tuple/1`, `Kernel.put_elem/3`, and `Kernel.tuple_size/1`. """ @doc """ Creates a new tuple. Creates a tuple of size `size` containing the given `data` at every position. Inlined by the compiler. ## Examples iex> Tuple.duplicate(:hello, 3) {:hello, :hello, :hello} """ @spec duplicate(term, non_neg_integer) :: tuple def duplicate(data, size) do :erlang.make_tuple(size, data) end @doc """ Inserts an element into a tuple. Inserts `value` into `tuple` at the given zero-based `index`. Raises an `ArgumentError` if `index` is negative or greater than the length of `tuple`. Inlined by the compiler. ## Examples iex> tuple = {:bar, :baz} iex> Tuple.insert_at(tuple, 0, :foo) {:foo, :bar, :baz} iex> Tuple.insert_at(tuple, 2, :bong) {:bar, :baz, :bong} """ @spec insert_at(tuple, non_neg_integer, term) :: tuple def insert_at(tuple, index, value) do :erlang.insert_element(index + 1, tuple, value) end @doc """ Inserts an element into the end of a tuple. Returns a new tuple which has one element more than `tuple`, and contains the elements in `tuple` followed by `value` as the last element. Inlined by the compiler. ## Examples iex> tuple = {:foo, :bar} iex> Tuple.append(tuple, :baz) {:foo, :bar, :baz} """ @spec append(tuple, term) :: tuple def append(tuple, value) do :erlang.append_element(tuple, value) end @doc """ Removes an element from a tuple. Deletes the element at the zero-based `index` from `tuple`. Raises an `ArgumentError` if `index` is negative or greater than or equal to the length of `tuple`. Inlined by the compiler. ## Examples iex> tuple = {:foo, :bar, :baz} iex> Tuple.delete_at(tuple, 0) {:bar, :baz} """ @spec delete_at(tuple, non_neg_integer) :: tuple def delete_at(tuple, index) do :erlang.delete_element(index + 1, tuple) end @doc """ Converts a tuple to a list. Inlined by the compiler. ## Examples iex> tuple = {:foo, :bar, :baz} iex> Tuple.to_list(tuple) [:foo, :bar, :baz] """ @spec to_list(tuple) :: list def to_list(tuple) do :erlang.tuple_to_list(tuple) end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/uri.ex000066400000000000000000000235001254730255300210620ustar00rootroot00000000000000defmodule URI do @moduledoc """ Utilities for working with and creating URIs. """ defstruct scheme: nil, path: nil, query: nil, fragment: nil, authority: nil, userinfo: nil, host: nil, port: nil @type t :: %__MODULE__{} import Bitwise @doc """ Returns the default port for a given scheme. If the scheme is unknown to URI, returns `nil`. Any scheme may be registered via `default_port/2`. ## Examples iex> URI.default_port("ftp") 21 iex> URI.default_port("ponzi") nil """ def default_port(scheme) when is_binary(scheme) do :elixir_config.get({:uri, scheme}) end @doc """ Registers a scheme with a default port. It is recommended for this function to be invoked in your application start callback in case you want to register new URIs. """ def default_port(scheme, port) when is_binary(scheme) and port > 0 do :elixir_config.put({:uri, scheme}, port) end @doc """ Encodes an enumerable into a query string. Takes an enumerable (containing a sequence of two-item tuples) and returns a string of the form "key1=value1&key2=value2..." where keys and values are URL encoded as per `encode/2`. Keys and values can be any term that implements the `String.Chars` protocol, except lists which are explicitly forbidden. ## Examples iex> hd = %{"foo" => 1, "bar" => 2} iex> URI.encode_query(hd) "bar=2&foo=1" """ def encode_query(l), do: Enum.map_join(l, "&", &pair/1) @doc """ Decodes a query string into a dictionary (by default uses a map). Given a query string of the form "key1=value1&key2=value2...", produces a map with one entry for each key-value pair. Each key and value will be a binary. Keys and values will be percent-unescaped. Use `query_decoder/1` if you want to iterate over each value manually. ## Examples iex> URI.decode_query("foo=1&bar=2") %{"bar" => "2", "foo" => "1"} """ def decode_query(q, dict \\ %{}) when is_binary(q) do case do_decode_query(q) do nil -> dict {{k, v}, q} -> decode_query(q, Dict.put(dict, k, v)) end end @doc """ Returns an iterator function over the query string that decodes the query string in steps. ## Examples iex> URI.query_decoder("foo=1&bar=2") |> Enum.map(&(&1)) [{"foo", "1"}, {"bar", "2"}] """ def query_decoder(q) when is_binary(q) do Stream.unfold(q, &do_decode_query/1) end defp do_decode_query("") do nil end defp do_decode_query(q) do {first, next} = case :binary.split(q, "&") do [first, rest] -> {first, rest} [first] -> {first, ""} end current = case :binary.split(first, "=") do [key, value] -> {decode_www_form(key), decode_www_form(value)} [key] -> {decode_www_form(key), nil} end {current, next} end defp pair({k, _}) when is_list(k) do raise ArgumentError, "encode_query/1 keys cannot be lists, got: #{inspect k}" end defp pair({_, v}) when is_list(v) do raise ArgumentError, "encode_query/1 values cannot be lists, got: #{inspect v}" end defp pair({k, v}) do encode_www_form(to_string(k)) <> "=" <> encode_www_form(to_string(v)) end @doc """ Checks if the character is a "reserved" character in a URI. Reserved characters are specified in RFC3986, section 2.2. """ def char_reserved?(c) do c in ':/?#[]@!$&\'()*+,;=' end @doc """ Checks if the character is a "unreserved" character in a URI. Unreserved characters are specified in RFC3986, section 2.3. """ def char_unreserved?(c) do c in ?0..?9 or c in ?a..?z or c in ?A..?Z or c in '~_-.' end @doc """ Checks if the character is allowed unescaped in a URI. This is the default used by `URI.encode/2` where both reserved and unreserved characters are kept unescaped. """ def char_unescaped?(c) do char_reserved?(c) or char_unreserved?(c) end @doc """ Percent-escapes a URI. Accepts `predicate` function as an argument to specify if char can be left as is. ## Example iex> URI.encode("ftp://s-ite.tld/?value=put it+й") "ftp://s-ite.tld/?value=put%20it+%D0%B9" """ def encode(str, predicate \\ &char_unescaped?/1) when is_binary(str) do for <>, into: "", do: percent(c, predicate) end @doc """ Encodes a string as "x-www-urlencoded". ## Example iex> URI.encode_www_form("put: it+й") "put%3A+it%2B%D0%B9" """ def encode_www_form(str) when is_binary(str) do for <>, into: "" do case percent(c, &char_unreserved?/1) do "%20" -> "+" pct -> pct end end end defp percent(c, predicate) do if predicate.(c) do <> else "%" <> hex(bsr(c, 4)) <> hex(band(c, 15)) end end defp hex(n) when n <= 9, do: <> defp hex(n), do: <> @doc """ Percent-unescapes a URI. ## Examples iex> URI.decode("http%3A%2F%2Felixir-lang.org") "http://elixir-lang.org" """ def decode(uri) do unpercent(uri, "", false) catch :malformed_uri -> raise ArgumentError, "malformed URI #{inspect uri}" end @doc """ Decodes a string as "x-www-urlencoded". ## Examples iex> URI.decode_www_form("%3Call+in%2F") " raise ArgumentError, "malformed URI #{inspect str}" end defp unpercent(<>, acc, spaces = true) do unpercent(tail, <>, spaces) end defp unpercent(<>, acc, spaces) do unpercent(tail, <>, spaces) end defp unpercent(<>, _acc, _spaces), do: throw(:malformed_uri) defp unpercent(<>, acc, spaces) do unpercent(tail, <>, spaces) end defp unpercent(<<>>, acc, _spaces), do: acc defp hex_to_dec(n) when n in ?A..?F, do: n - ?A + 10 defp hex_to_dec(n) when n in ?a..?f, do: n - ?a + 10 defp hex_to_dec(n) when n in ?0..?9, do: n - ?0 defp hex_to_dec(_n), do: throw(:malformed_uri) @doc """ Parses a well-formed URI reference into its components. Note this function expects a well-formed URI and does not perform any validation. See the examples section below of how `URI.parse/1` can be used to parse a wide range of relative URIs. This function uses the parsing regular expression as defined in the Appendix B of RFC3986. When a URI is given without a port, the values registered via `URI.default_port/1` and `URI.default_port/2` are used. ## Examples iex> URI.parse("http://elixir-lang.org/") %URI{scheme: "http", path: "/", query: nil, fragment: nil, authority: "elixir-lang.org", userinfo: nil, host: "elixir-lang.org", port: 80} iex> URI.parse("//elixir-lang.org/") %URI{authority: "elixir-lang.org", fragment: nil, host: "elixir-lang.org", path: "/", port: nil, query: nil, scheme: nil, userinfo: nil} iex> URI.parse("/foo/bar") %URI{authority: nil, fragment: nil, host: nil, path: "/foo/bar", port: nil, query: nil, scheme: nil, userinfo: nil} iex> URI.parse("foo/bar") %URI{authority: nil, fragment: nil, host: nil, path: "foo/bar", port: nil, query: nil, scheme: nil, userinfo: nil} """ def parse(%URI{} = uri), do: uri def parse(s) when is_binary(s) do # From http://tools.ietf.org/html/rfc3986#appendix-B regex = ~r/^(([a-z][a-z0-9\+\-\.]*):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/i parts = nillify(Regex.run(regex, s)) destructure [_, _, scheme, _, authority, path, _, query, _, fragment], parts {userinfo, host, port} = split_authority(authority) if authority do authority = "" if userinfo, do: authority = authority <> userinfo <> "@" if host, do: authority = authority <> host if port, do: authority = authority <> ":" <> Integer.to_string(port) end scheme = normalize_scheme(scheme) if is_nil(port) and not is_nil(scheme) do port = default_port(scheme) end %URI{ scheme: scheme, path: path, query: query, fragment: fragment, authority: authority, userinfo: userinfo, host: host, port: port } end # Split an authority into its userinfo, host and port parts. defp split_authority(s) do s = s || "" components = Regex.run ~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/, s destructure [_, _, userinfo, host, _, port], nillify(components) port = if port, do: String.to_integer(port) host = if host, do: host |> String.lstrip(?[) |> String.rstrip(?]) {userinfo, host, port} end defp normalize_scheme(nil), do: nil defp normalize_scheme(scheme), do: String.downcase(scheme) # Regex.run returns empty strings sometimes. We want # to replace those with nil for consistency. defp nillify(l) do for s <- l do if byte_size(s) > 0, do: s, else: nil end end end defimpl String.Chars, for: URI do def to_string(uri) do scheme = uri.scheme if scheme && (port = URI.default_port(scheme)) do if uri.port == port, do: uri = %{uri | port: nil} end # Based on http://tools.ietf.org/html/rfc3986#section-5.3 if uri.host do authority = uri.host if uri.userinfo, do: authority = uri.userinfo <> "@" <> authority if uri.port, do: authority = authority <> ":" <> Integer.to_string(uri.port) else authority = uri.authority end result = "" if uri.scheme, do: result = result <> uri.scheme <> ":" if authority, do: result = result <> "//" <> authority if uri.path, do: result = result <> uri.path if uri.query, do: result = result <> "?" <> uri.query if uri.fragment, do: result = result <> "#" <> uri.fragment result end end elixir-lang-1.1.0~0.20150708/lib/elixir/lib/version.ex000066400000000000000000000364441254730255300217630ustar00rootroot00000000000000defmodule Version do @moduledoc ~S""" Functions for parsing and matching versions against requirements. A version is a string in a specific format or a `Version` generated after parsing via `Version.parse/1`. `Version` parsing and requirements follow [SemVer 2.0 schema](http://semver.org/). ## Versions In a nutshell, a version is given by three numbers: MAJOR.MINOR.PATCH Pre-releases are supported by appending `-[0-9A-Za-z-\.]`: "1.0.0-alpha.3" Build information can be added by appending `+[0-9A-Za-z-\.]`: "1.0.0-alpha.3+20130417140000" ## Struct The version is represented by the Version struct and it has its fields named according to Semver: `:major`, `:minor`, `:patch`, `:pre` and `:build`. ## Requirements Requirements allow you to specify which versions of a given dependency you are willing to work against. It supports common operators like `>=`, `<=`, `>`, `==` and friends that work as one would expect: # Only version 2.0.0 "== 2.0.0" # Anything later than 2.0.0 "> 2.0.0" Requirements also support `and` and `or` for complex conditions: # 2.0.0 and later until 2.1.0 ">= 2.0.0 and < 2.1.0" Since the example above is such a common requirement, it can be expressed as: "~> 2.0.0" `~>` will never include pre-release versions of its upper bound. It can also be used to set an upper bound on only the major version part. See the table below for `~>` requirements and their corresponding translation. `~>` | Translation :------------- | :--------------------- `~> 2.0.0` | `>= 2.0.0 and < 2.1.0` `~> 2.1.2` | `>= 2.1.2 and < 2.2.0` `~> 2.1.3-dev` | `>= 2.1.3-dev and < 2.2.0` `~> 2.0` | `>= 2.0.0 and < 3.0.0` `~> 2.1` | `>= 2.1.0 and < 3.0.0` """ import Kernel, except: [match?: 2] defstruct [:major, :minor, :patch, :pre, :build] @type version :: String.t | t @type requirement :: String.t | Version.Requirement.t @type major :: String.t | non_neg_integer @type minor :: non_neg_integer | nil @type patch :: non_neg_integer | nil @type pre :: [String.t | non_neg_integer] @type build :: String.t | nil @type matchable :: {major :: major, minor :: minor, patch :: patch, pre :: pre} @type t :: %__MODULE__{ major: major, minor: minor, patch: patch, pre: pre, build: build} defmodule Requirement do defstruct [:source, :matchspec] @type t :: %__MODULE__{} end defmodule InvalidRequirementError do defexception [:message] end defmodule InvalidVersionError do defexception [:message] end @doc """ Checks if the given version matches the specification. Returns `true` if `version` satisfies `requirement`, `false` otherwise. Raises a `Version.InvalidRequirementError` exception if `requirement` is not parseable, or `Version.InvalidVersionError` if `version` is not parseable. If given an already parsed version and requirement this function won't raise. ## Examples iex> Version.match?("2.0.0", ">1.0.0") true iex> Version.match?("2.0.0", "==1.0.0") false iex> Version.match?("foo", "==1.0.0") ** (Version.InvalidVersionError) foo iex> Version.match?("2.0.0", "== ==1.0.0") ** (Version.InvalidRequirementError) == ==1.0.0 """ @spec match?(version, requirement) :: boolean def match?(version, requirement) when is_binary(requirement) do case parse_requirement(requirement) do {:ok, requirement} -> match?(version, requirement) :error -> raise InvalidRequirementError, message: requirement end end def match?(version, %Requirement{matchspec: spec}) do {:ok, result} = :ets.test_ms(to_matchable(version), spec) result != false end @doc """ Compares two versions. Returns `:gt` if first version is greater than the second and `:lt` for vice versa. If the two versions are equal `:eq` is returned Raises a `Version.InvalidVersionError` exception if `version` is not parseable. If given an already parsed version this function won't raise. ## Examples iex> Version.compare("2.0.1-alpha1", "2.0.0") :gt iex> Version.compare("2.0.1+build0", "2.0.1") :eq iex> Version.compare("invalid", "2.0.1") ** (Version.InvalidVersionError) invalid """ @spec compare(version, version) :: :gt | :eq | :lt def compare(version1, version2) do do_compare(to_matchable(version1), to_matchable(version2)) end defp do_compare({major1, minor1, patch1, pre1}, {major2, minor2, patch2, pre2}) do cond do {major1, minor1, patch1} > {major2, minor2, patch2} -> :gt {major1, minor1, patch1} < {major2, minor2, patch2} -> :lt pre1 == [] and pre2 != [] -> :gt pre1 != [] and pre2 == [] -> :lt pre1 > pre2 -> :gt pre1 < pre2 -> :lt true -> :eq end end @doc """ Parses a version string into a `Version`. ## Examples iex> {:ok, version} = Version.parse("2.0.1-alpha1") iex> version #Version<2.0.1-alpha1> iex> Version.parse("2.0-alpha1") :error """ @spec parse(String.t) :: {:ok, t} | :error def parse(string) when is_binary(string) do case Version.Parser.parse_version(string) do {:ok, {major, minor, patch, pre}} -> version = %Version{major: major, minor: minor, patch: patch, pre: pre, build: get_build(string)} {:ok, version} :error -> :error end end @doc """ Parses a version requirement string into a `Version.Requirement`. ## Examples iex> {:ok, req} = Version.parse_requirement("== 2.0.1") iex> req #Version.Requirement<== 2.0.1> iex> Version.parse_requirement("== == 2.0.1") :error """ @spec parse_requirement(String.t) :: {:ok, Requirement.t} | :error def parse_requirement(string) when is_binary(string) do case Version.Parser.parse_requirement(string) do {:ok, spec} -> {:ok, %Requirement{source: string, matchspec: spec}} :error -> :error end end defp to_matchable(%Version{major: major, minor: minor, patch: patch, pre: pre}) do {major, minor, patch, pre} end defp to_matchable(string) do case Version.Parser.parse_version(string) do {:ok, version} -> version :error -> raise InvalidVersionError, message: string end end defp get_build(string) do case Regex.run(~r/\+([^\s]+)$/, string) do nil -> nil [_, build] -> build end end defmodule Parser.DSL do @moduledoc false defmacro deflexer(match, do: body) when is_binary(match) do quote do def lexer(unquote(match) <> rest, acc) do lexer(rest, [unquote(body) | acc]) end end end defmacro deflexer(acc, do: body) do quote do def lexer("", unquote(acc)) do unquote(body) end end end defmacro deflexer(char, acc, do: body) do quote do def lexer(<< unquote(char) :: utf8, rest :: binary >>, unquote(acc)) do unquote(char) = << unquote(char) :: utf8 >> lexer(rest, unquote(body)) end end end end defmodule Parser do @moduledoc false import Parser.DSL deflexer ">=", do: :'>=' deflexer "<=", do: :'<=' deflexer "~>", do: :'~>' deflexer ">", do: :'>' deflexer "<", do: :'<' deflexer "==", do: :'==' deflexer "!=", do: :'!=' deflexer "!", do: :'!=' deflexer " or ", do: :'||' deflexer " and ", do: :'&&' deflexer " ", do: :' ' deflexer x, [] do [x, :'=='] end deflexer x, [h | acc] do cond do is_binary h -> [h <> x | acc] h in [:'||', :'&&'] -> [x, :'==', h | acc] true -> [x, h | acc] end end deflexer acc do Enum.filter(Enum.reverse(acc), &(&1 != :' ')) end @version_regex ~r/^ (\d+) # major (?:\.(\d+))? # minor (?:\.(\d+))? # patch (?:\-([\d\w\.\-]+))? # pre (?:\+([\d\w\-]+))? # build $/x @spec parse_requirement(String.t) :: {:ok, Version.Requirement.t} | :error def parse_requirement(source) do lexed = lexer(source, []) to_matchspec(lexed) end defp nillify(""), do: nil defp nillify(o), do: o @spec parse_version(String.t) :: {:ok, Version.matchable} | :error def parse_version(string, approximate? \\ false) when is_binary(string) do if parsed = Regex.run(@version_regex, string) do destructure [_, major, minor, patch, pre], parsed patch = nillify(patch) pre = nillify(pre) if is_nil(minor) or (is_nil(patch) and not approximate?) do :error else major = String.to_integer(major) minor = String.to_integer(minor) patch = patch && String.to_integer(patch) case parse_pre(pre) do {:ok, pre} -> {:ok, {major, minor, patch, pre}} :error -> :error end end else :error end end defp parse_pre(nil), do: {:ok, []} defp parse_pre(pre), do: parse_pre(String.split(pre, "."), []) defp parse_pre([piece|t], acc) do cond do piece =~ ~r/^(0|[1-9][0-9]*)$/ -> parse_pre(t, [String.to_integer(piece)|acc]) piece =~ ~r/^[0-9]*$/ -> :error true -> parse_pre(t, [piece|acc]) end end defp parse_pre([], acc) do {:ok, Enum.reverse(acc)} end defp valid_requirement?([]), do: false defp valid_requirement?([a | next]), do: valid_requirement?(a, next) # it must finish with a version defp valid_requirement?(a, []) when is_binary(a) do true end # or | and defp valid_requirement?(a, [b | next]) when is_atom(a) and is_atom(b) and a in [:'||', :'&&'] do valid_requirement?(b, next) end # or | and defp valid_requirement?(a, [b | next]) when is_binary(a) and is_atom(b) and b in [:'||', :'&&'] do valid_requirement?(b, next) end # or | and defp valid_requirement?(a, [b | next]) when is_atom(a) and is_binary(b) and a in [:'||', :'&&'] do valid_requirement?(b, next) end # defp valid_requirement?(a, [b | next]) when is_atom(a) and is_binary(b) do valid_requirement?(b, next) end defp valid_requirement?(_, _) do false end defp approximate_upper(version) do case version do {major, _minor, nil, _} -> {major + 1, 0, 0, [0]} {major, minor, _patch, _} -> {major, minor + 1, 0, [0]} end end defp to_matchspec(lexed) do if valid_requirement?(lexed) do first = to_condition(lexed) rest = Enum.drop(lexed, 2) {:ok, [{{:'$1', :'$2', :'$3', :'$4'}, [to_condition(first, rest)], [:'$_']}]} else :error end catch :invalid_matchspec -> :error end defp to_condition([:'==', version | _]) do version = parse_condition(version) {:'==', :'$_', {:const, version}} end defp to_condition([:'!=', version | _]) do version = parse_condition(version) {:'/=', :'$_', {:const, version}} end defp to_condition([:'~>', version | _]) do from = parse_condition(version, true) to = approximate_upper(from) {:andalso, to_condition([:'>=', matchable_to_string(from)]), to_condition([:'<', matchable_to_string(to)])} end defp to_condition([:'>', version | _]) do {major, minor, patch, pre} = parse_condition(version) {:orelse, {:'>', {{:'$1', :'$2', :'$3'}}, {:const, {major, minor, patch}}}, {:andalso, {:'==', {{:'$1', :'$2', :'$3'}}, {:const, {major, minor, patch}}}, {:orelse, {:andalso, {:'==', {:length, :'$4'}, 0}, {:'/=', length(pre), 0}}, {:andalso, {:'/=', length(pre), 0}, {:orelse, {:'>', {:length, :'$4'}, length(pre)}, {:andalso, {:'==', {:length, :'$4'}, length(pre)}, {:'>', :'$4', {:const, pre}}}}}}}} end defp to_condition([:'>=', version | _]) do matchable = parse_condition(version) {:orelse, {:'==', :'$_', {:const, matchable}}, to_condition([:'>', version])} end defp to_condition([:'<', version | _]) do {major, minor, patch, pre} = parse_condition(version) {:orelse, {:'<', {{:'$1', :'$2', :'$3'}}, {:const, {major, minor, patch}}}, {:andalso, {:'==', {{:'$1', :'$2', :'$3'}}, {:const, {major, minor, patch}}}, {:orelse, {:andalso, {:'/=', {:length, :'$4'}, 0}, {:'==', length(pre), 0}}, {:andalso, {:'/=', {:length, :'$4'}, 0}, {:orelse, {:'<', {:length, :'$4'}, length(pre)}, {:andalso, {:'==', {:length, :'$4'}, length(pre)}, {:'<', :'$4', {:const, pre}}}}}}}} end defp to_condition([:'<=', version | _]) do matchable = parse_condition(version) {:orelse, {:'==', :'$_', {:const, matchable}}, to_condition([:'<', version])} end defp to_condition(current, []) do current end defp to_condition(current, [:'&&', operator, version | rest]) do to_condition({:andalso, current, to_condition([operator, version])}, rest) end defp to_condition(current, [:'||', operator, version | rest]) do to_condition({:orelse, current, to_condition([operator, version])}, rest) end defp parse_condition(version, approximate? \\ false) do case parse_version(version, approximate?) do {:ok, version} -> version :error -> throw :invalid_matchspec end end defp matchable_to_string({major, minor, patch, pre}) do patch = if patch, do: "#{patch}", else: "0" pre = if pre != [], do: "-#{Enum.join(pre, ".")}" "#{major}.#{minor}.#{patch}#{pre}" end end end defimpl String.Chars, for: Version do def to_string(version) do pre = pre(version.pre) build = if build = version.build, do: "+#{build}" "#{version.major}.#{version.minor}.#{version.patch}#{pre}#{build}" end defp pre([]) do "" end defp pre(pre) do "-" <> Enum.map_join(pre, ".", fn int when is_integer(int) -> Integer.to_string(int) string when is_binary(string) -> string end) end end defimpl Inspect, for: Version do def inspect(self, _opts) do "#Version<" <> to_string(self) <> ">" end end defimpl String.Chars, for: Version.Requirement do def to_string(%Version.Requirement{source: source}) do source end end defimpl Inspect, for: Version.Requirement do def inspect(%Version.Requirement{source: source}, _opts) do "#Version.Requirement<" <> source <> ">" end end elixir-lang-1.1.0~0.20150708/lib/elixir/mix.exs000066400000000000000000000002361254730255300204760ustar00rootroot00000000000000defmodule Elixir.Mixfile do use Mix.Project def project do [app: :elixir, version: System.version, build_per_environment: false] end end elixir-lang-1.1.0~0.20150708/lib/elixir/rebar.config000066400000000000000000000011601254730255300214370ustar00rootroot00000000000000{erl_opts, [ warn_unused_vars, warn_export_all, warn_shadow_vars, warn_unused_import, warn_unused_function, warn_bif_clash, warn_unused_record, warn_deprecated_function, warn_obsolete_guard, strict_validation, warn_exported_vars, %% warn_export_vars, %% warn_missing_spec, %% warn_untyped_record, %% warnings_as_errors, debug_info ]}. {yrl_opts, [ {report, true}, {verbose, false} ]}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/000077500000000000000000000000001254730255300177465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir.erl000066400000000000000000000215061254730255300217520ustar00rootroot00000000000000%% Main entry point for Elixir functions. All of those functions are %% private to the Elixir compiler and reserved to be used by Elixir only. -module(elixir). -behaviour(application). -export([start_cli/0, string_to_quoted/4, 'string_to_quoted!'/4, env_for_eval/1, env_for_eval/2, quoted_to_erl/2, quoted_to_erl/3, eval/2, eval/3, eval_forms/3, eval_forms/4, eval_quoted/3]). -include("elixir.hrl"). %% Top level types -export_type([char_list/0, as_boolean/1]). -type char_list() :: string(). -type as_boolean(T) :: T. %% OTP Application API -export([start/2, stop/1, config_change/3]). start(_Type, _Args) -> %% In case there is a shell, we can't really change its %% encoding, so we just set binary to true. Otherwise %% we must set the encoding as the user with no shell %% has encoding set to latin1. Opts = case init:get_argument(noshell) of {ok, _} -> [binary, {encoding, utf8}]; error -> [binary] end, ok = io:setopts(standard_io, Opts), %% TODO: Remove this once we support only OTP >18 ok = case io:setopts(standard_error, [{encoding, utf8}]) of ok -> ok; {error, _} -> io:setopts(standard_error, [{unicode, true}]) %% OTP 17.3 and earlier end, Encoding = file:native_name_encoding(), case Encoding of latin1 -> io:format(standard_error, "warning: the VM is running with native name encoding of latin1 which may cause " "Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 " "(which can be verified by running \"locale\" in your shell)~n", []); _ -> ok end, URIs = [{<<"ftp">>, 21}, {<<"sftp">>, 22}, {<<"tftp">>, 69}, {<<"http">>, 80}, {<<"https">>, 443}, {<<"ldap">>, 389}], URIConfig = [{{uri, Scheme}, Port} || {Scheme, Port} <- URIs], CompilerOpts = [{docs, true}, {debug_info, true}, {warnings_as_errors, false}], {ok, [[Home] | _]} = init:get_argument(home), Config = [{at_exit, []}, {home, unicode:characters_to_binary(Home, Encoding, Encoding)}, {compiler_options, orddict:from_list(CompilerOpts)} | URIConfig], Tab = elixir_config:new(Config), case elixir_sup:start_link() of {ok, Sup} -> {ok, Sup, Tab}; {error, _Reason} = Error -> elixir_config:delete(Tab), Error end. stop(Tab) -> elixir_config:delete(Tab). config_change(_Changed, _New, _Remove) -> ok. %% Boot and process given options. Invoked by Elixir's script. start_cli() -> {ok, _} = application:ensure_all_started(?MODULE), %% We start the Logger so tools that depend on Elixir %% always have the Logger directly accessible. However %% Logger is not a dependency of the Elixir application, %% which means releases that want to use Logger must %% always list it as part of its applications. _ = case code:ensure_loaded('Elixir.Logger') of {module, _} -> application:start(logger); {error, _} -> ok end, 'Elixir.Kernel.CLI':main(init:get_plain_arguments()). %% EVAL HOOKS env_for_eval(Opts) -> env_for_eval((elixir_env:new())#{ requires := elixir_dispatch:default_requires(), functions := elixir_dispatch:default_functions(), macros := elixir_dispatch:default_macros() }, Opts). env_for_eval(Env, Opts) -> Line = case lists:keyfind(line, 1, Opts) of {line, LineOpt} when is_integer(LineOpt) -> LineOpt; false -> ?m(Env, line) end, File = case lists:keyfind(file, 1, Opts) of {file, FileOpt} when is_binary(FileOpt) -> FileOpt; false -> ?m(Env, file) end, Aliases = case lists:keyfind(aliases, 1, Opts) of {aliases, AliasesOpt} when is_list(AliasesOpt) -> AliasesOpt; false -> ?m(Env, aliases) end, Requires = case lists:keyfind(requires, 1, Opts) of {requires, RequiresOpt} when is_list(RequiresOpt) -> ordsets:from_list(RequiresOpt); false -> ?m(Env, requires) end, Functions = case lists:keyfind(functions, 1, Opts) of {functions, FunctionsOpt} when is_list(FunctionsOpt) -> FunctionsOpt; false -> ?m(Env, functions) end, Macros = case lists:keyfind(macros, 1, Opts) of {macros, MacrosOpt} when is_list(MacrosOpt) -> MacrosOpt; false -> ?m(Env, macros) end, Module = case lists:keyfind(module, 1, Opts) of {module, ModuleOpt} when is_atom(ModuleOpt) -> ModuleOpt; false -> nil end, Env#{ file := File, module := Module, macros := Macros, functions := Functions, requires := Requires, aliases := Aliases, line := Line }. %% String evaluation eval(String, Binding) -> eval(String, Binding, []). eval(String, Binding, Opts) when is_list(Opts) -> eval(String, Binding, env_for_eval(Opts)); eval(String, Binding, #{line := Line, file := File} = E) when is_list(String), is_list(Binding), is_integer(Line), is_binary(File) -> Forms = 'string_to_quoted!'(String, Line, File, []), eval_forms(Forms, Binding, E). %% Quoted evaluation eval_quoted(Tree, Binding, Opts) when is_list(Opts) -> eval_quoted(Tree, Binding, env_for_eval(Opts)); eval_quoted(Tree, Binding, #{line := Line} = E) -> eval_forms(elixir_quote:linify(Line, Tree), Binding, E). %% Handle forms evaluation. The main difference to %% to eval_quoted is that it does not linefy the given %% args. eval_forms(Tree, Binding, Opts) when is_list(Opts) -> eval_forms(Tree, Binding, env_for_eval(Opts)); eval_forms(Tree, Binding, E) -> eval_forms(Tree, Binding, E, elixir_env:env_to_scope(E)). eval_forms(Tree, Binding, Env, Scope) -> {ParsedBinding, ParsedScope} = elixir_scope:load_binding(Binding, Scope), ParsedEnv = Env#{vars := [K || {K, _} <- ParsedScope#elixir_scope.vars]}, {Erl, NewEnv, NewScope} = quoted_to_erl(Tree, ParsedEnv, ParsedScope), case Erl of {atom, _, Atom} -> {Atom, Binding, NewEnv, NewScope}; _ -> {value, Value, NewBinding} = erl_eval(Erl, ParsedBinding, Env), {Value, elixir_scope:dump_binding(NewBinding, NewScope), NewEnv, NewScope} end. erl_eval(Erl, ParsedBinding, E) -> case erl_eval:check_command([Erl], ParsedBinding) of ok -> ok; {error, Desc} -> elixir_errors:handle_file_error(?m(E, file), Desc) end, % Below must be all one line for locations to be the same when the stacktrace % needs to be extended to the full stacktrace. try erl_eval:expr(Erl, ParsedBinding, none, none, none) catch Class:Exception -> erlang:raise(Class, Exception, get_stacktrace()) end. get_stacktrace() -> Stacktrace = erlang:get_stacktrace(), % eval_eval and eval_bits can call :erlang.raise/3 without the full % stacktrace. When this occurs re-add the current stacktrace so that no % stack information is lost. try throw(stack) catch throw:stack -> % Ignore stack item for current function. [_ | CurrentStack] = erlang:get_stacktrace(), get_stacktrace(Stacktrace, CurrentStack) end. % The stacktrace did not include the current stack, re-add it. get_stacktrace([], CurrentStack) -> CurrentStack; % The stacktrace includes the current stack. get_stacktrace(CurrentStack, CurrentStack) -> CurrentStack; get_stacktrace([StackItem | Stacktrace], CurrentStack) -> [StackItem | get_stacktrace(Stacktrace, CurrentStack)]. %% Converts a quoted expression to erlang abstract format quoted_to_erl(Quoted, Env) -> quoted_to_erl(Quoted, Env, elixir_env:env_to_scope(Env)). quoted_to_erl(Quoted, Env, Scope) -> {Expanded, NewEnv} = elixir_exp:expand(Quoted, Env), {Erl, NewScope} = elixir_translator:translate(Expanded, Scope), {Erl, NewEnv, NewScope}. %% Converts a given string (char list) into quote expression string_to_quoted(String, StartLine, File, Opts) when is_integer(StartLine), is_binary(File) -> case elixir_tokenizer:tokenize(String, StartLine, [{file, File}|Opts]) of {ok, _Line, _Column, Tokens} -> try elixir_parser:parse(Tokens) of {ok, Forms} -> {ok, Forms}; {error, {{Line, _, _}, _, [Error, Token]}} -> {error, {Line, to_binary(Error), to_binary(Token)}}; {error, {Line, _, [Error, Token]}} -> {error, {Line, to_binary(Error), to_binary(Token)}} catch {error, {{Line, _, _}, _, [Error, Token]}} -> {error, {Line, to_binary(Error), to_binary(Token)}}; {error, {Line, _, [Error, Token]}} -> {error, {Line, to_binary(Error), to_binary(Token)}} end; {error, {Line, {ErrorPrefix, ErrorSuffix}, Token}, _Rest, _SoFar} -> {error, {Line, {to_binary(ErrorPrefix), to_binary(ErrorSuffix)}, to_binary(Token)}}; {error, {Line, Error, Token}, _Rest, _SoFar} -> {error, {Line, to_binary(Error), to_binary(Token)}} end. 'string_to_quoted!'(String, StartLine, File, Opts) -> case string_to_quoted(String, StartLine, File, Opts) of {ok, Forms} -> Forms; {error, {Line, Error, Token}} -> elixir_errors:parse_error(Line, File, Error, Token) end. to_binary(List) when is_list(List) -> elixir_utils:characters_to_binary(List); to_binary(Atom) when is_atom(Atom) -> atom_to_binary(Atom, utf8). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir.hrl000066400000000000000000000053031254730255300217520ustar00rootroot00000000000000-define(m(M, K), maps:get(K, M)). -define(line(Opts), elixir_utils:get_line(Opts)). -record(elixir_scope, { context=nil, %% can be match, guards or nil extra=nil, %% extra information about the context, like fn_match and map_key noname=false, %% when true, don't add new names (used by try) super=false, %% when true, it means super was invoked caller=false, %% when true, it means caller was invoked return=true, %% when true, the return value is used module=nil, %% the current module function=nil, %% the current function vars=[], %% a dict of defined variables and their alias backup_vars=nil, %% a copy of vars to be used on ^var match_vars=nil, %% a set of all variables defined in a particular match export_vars=nil, %% a dict of all variables defined in a particular clause extra_guards=nil, %% extra guards from args expansion counter=[], %% a dict counting the variables defined file=(<<"nofile">>) %% the current scope filename }). -record(elixir_quote, { line=false, file=nil, context=nil, vars_hygiene=true, aliases_hygiene=true, imports_hygiene=true, unquote=true, unquoted=false, escape=false }). -record(elixir_tokenizer, { file, terminators=[], check_terminators=true, existing_atoms_only=false }). %% Used in tokenization and interpolation %% Numbers -define(is_hex(S), (?is_digit(S) orelse (S >= $A andalso S =< $F) orelse (S >= $a andalso S =< $f))). -define(is_bin(S), (S >= $0 andalso S =< $1)). -define(is_octal(S), (S >= $0 andalso S =< $7)). -define(is_leading_octal(S), (S >= $0 andalso S =< $3)). %% Digits and letters -define(is_digit(S), (S >= $0 andalso S =< $9)). -define(is_upcase(S), (S >= $A andalso S =< $Z)). -define(is_downcase(S), (S >= $a andalso S =< $z)). %% Atoms -define(is_atom_start(S), (?is_quote(S) orelse ?is_upcase(S) orelse ?is_downcase(S) orelse (S == $_))). -define(is_atom(S), (?is_identifier(S) orelse (S == $@))). -define(is_identifier_start(S), (?is_upcase(S) orelse ?is_downcase(S) orelse (S == $_))). -define(is_identifier(S), (?is_digit(S) orelse ?is_identifier_start(S))). -define(is_sigil(S), ((S == $/) orelse (S == $<) orelse (S == $") orelse (S == $') orelse (S == $[) orelse (S == $() orelse (S == ${) orelse (S == $|))). %% Quotes -define(is_quote(S), (S == $" orelse S == $')). %% Spaces -define(is_horizontal_space(S), ((S == $\s) orelse (S == $\t))). -define(is_vertical_space(S), ((S == $\r) orelse (S == $\n))). -define(is_space(S), (?is_horizontal_space(S) orelse ?is_vertical_space(S))). -define(is_invalid_space(S), (S == 16#A0)). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_aliases.erl000066400000000000000000000110411254730255300234440ustar00rootroot00000000000000-module(elixir_aliases). -export([inspect/1, last/1, concat/1, safe_concat/1, format_error/1, ensure_loaded/3, expand/4, store/7]). -include("elixir.hrl"). inspect(Atom) when is_atom(Atom) -> case elixir_compiler:get_opt(internal) of true -> atom_to_binary(Atom, utf8); false -> 'Elixir.Inspect.Atom':inspect(Atom) end. %% Store an alias in the given scope store(_Meta, New, New, _TKV, Aliases, MacroAliases, _Lexical) -> {Aliases, MacroAliases}; store(Meta, New, Old, TKV, Aliases, MacroAliases, Lexical) -> record_warn(Meta, New, TKV, Lexical), {store_alias(New, Old, Aliases), store_macro_alias(Meta, New, Old, MacroAliases)}. store_alias(New, Old, Aliases) -> lists:keystore(New, 1, Aliases, {New, Old}). store_macro_alias(Meta, New, Old, Aliases) -> case lists:keymember(context, 1, Meta) andalso lists:keyfind(counter, 1, Meta) of {counter, Counter} when is_integer(Counter) -> lists:keystore(New, 1, Aliases, {New, {Counter, Old}}); _ -> Aliases end. record_warn(Meta, Ref, Opts, Lexical) -> Warn = case lists:keyfind(warn, 1, Opts) of {warn, false} -> false; {warn, true} -> true; false -> not lists:keymember(context, 1, Meta) end, elixir_lexical:record_alias(Ref, ?line(Meta), Warn, Lexical). %% Expand an alias. It returns an atom (meaning that there %% was an expansion) or a list of atoms. expand({'__aliases__', _Meta, ['Elixir'|_] = List}, _Aliases, _MacroAliases, _LexicalTracker) -> concat(List); expand({'__aliases__', Meta, _} = Alias, Aliases, MacroAliases, LexicalTracker) -> case lists:keyfind(alias, 1, Meta) of {alias, false} -> expand(Alias, MacroAliases, LexicalTracker); {alias, Atom} when is_atom(Atom) -> Atom; false -> expand(Alias, Aliases, LexicalTracker) end. expand({'__aliases__', Meta, [H|T]}, Aliases, LexicalTracker) when is_atom(H) -> Lookup = list_to_atom("Elixir." ++ atom_to_list(H)), Counter = case lists:keyfind(counter, 1, Meta) of {counter, C} -> C; _ -> nil end, case lookup(Lookup, Aliases, Counter) of Lookup -> [H|T]; Atom -> elixir_lexical:record_alias(Lookup, LexicalTracker), case T of [] -> Atom; _ -> concat([Atom|T]) end end; expand({'__aliases__', _Meta, List}, _Aliases, _LexicalTracker) -> List. %% Ensure a module is loaded before its usage. ensure_loaded(_Meta, 'Elixir.Kernel', _E) -> ok; ensure_loaded(Meta, Ref, E) -> try Ref:module_info(compile) catch error:undef -> Kind = case lists:member(Ref, ?m(E, context_modules)) of true -> scheduled_module; false -> unloaded_module end, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, {Kind, Ref}) end. %% Receives an atom and returns the last bit as an alias. last(Atom) -> Last = last(lists:reverse(atom_to_list(Atom)), []), list_to_atom("Elixir." ++ Last). last([$.|_], Acc) -> Acc; last([H|T], Acc) -> last(T, [H|Acc]); last([], Acc) -> Acc. %% Receives a list of atoms, binaries or lists %% representing modules and concatenates them. concat(Args) -> binary_to_atom(do_concat(Args), utf8). safe_concat(Args) -> binary_to_existing_atom(do_concat(Args), utf8). do_concat([H|T]) when is_atom(H), H /= nil -> do_concat([atom_to_binary(H, utf8)|T]); do_concat([<<"Elixir.", _/binary>>=H|T]) -> do_concat(T, H); do_concat([<<"Elixir">>=H|T]) -> do_concat(T, H); do_concat(T) -> do_concat(T, <<"Elixir">>). do_concat([nil|T], Acc) -> do_concat(T, Acc); do_concat([H|T], Acc) when is_atom(H) -> do_concat(T, <>); do_concat([H|T], Acc) when is_binary(H) -> do_concat(T, <>); do_concat([], Acc) -> Acc. to_partial(<<"Elixir.", Arg/binary>>) -> Arg; to_partial(<<".", Arg/binary>>) -> Arg; to_partial(Arg) when is_binary(Arg) -> Arg. %% Lookup an alias in the current scope. lookup(Else, Dict, Counter) -> case lists:keyfind(Else, 1, Dict) of {Else, {Counter, Value}} -> lookup(Value, Dict, Counter); {Else, Value} when is_atom(Value) -> lookup(Value, Dict, Counter); _ -> Else end. %% Errors format_error({unloaded_module, Module}) -> io_lib:format("module ~ts is not loaded and could not be found", [elixir_aliases:inspect(Module)]); format_error({scheduled_module, Module}) -> io_lib:format("module ~ts is not loaded but was defined. This happens because you are trying to use a module in the same context it is defined. Try defining the module outside the context that requires it.", [inspect(Module)]).elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_bitstring.erl000066400000000000000000000223021254730255300240320ustar00rootroot00000000000000-module(elixir_bitstring). -export([translate/3, expand/3, has_size/1]). -include("elixir.hrl"). %% Expansion expand(Meta, Args, E) -> case ?m(E, context) of match -> {EArgs, EA} = expand_bitstr(fun elixir_exp:expand/2, Args, [], E), {{'<<>>', Meta, EArgs}, EA}; _ -> {EArgs, {EC, EV}} = expand_bitstr(fun elixir_exp:expand_arg/2, Args, [], {E, E}), {{'<<>>', Meta, EArgs}, elixir_env:mergea(EV, EC)} end. expand_bitstr(_Fun, [], Acc, E) -> {lists:reverse(Acc), E}; expand_bitstr(Fun, [{'::', Meta, [Left, Right]}|T], Acc, E) -> {ELeft, EL} = Fun(Left, E), %% Variables defined outside the binary can be accounted %% on subparts, however we can't assign new variables. case E of {ER, _} -> ok; %% expand_arg, no assigns _ -> ER = E#{context := nil} %% expand_each, revert assigns end, ERight = expand_bit_info(Meta, Right, ER), expand_bitstr(Fun, T, [{'::', Meta, [ELeft, ERight]}|Acc], EL); expand_bitstr(Fun, [H|T], Acc, E) -> {Expr, ES} = Fun(H, E), expand_bitstr(Fun, T, [Expr|Acc], ES). %% Expand bit info expand_bit_info(Meta, Info, E) -> expand_bit_info(Meta, unpack_bit_info(Info, []), default, [], E). expand_bit_info(Meta, [{size, _, [_]=Args}|T], Size, Types, E) -> case Size of default -> {[EArg], EE} = elixir_exp:expand_args(Args, E), case EArg of {Var, _, Context} when is_atom(Var) and is_atom(Context) -> ok; _ when is_integer(EArg) -> ok; _ -> elixir_errors:compile_error(Meta, ?m(E, file), "size in bitstring expects an integer or a variable as argument, got: ~ts", ['Elixir.Macro':to_string(EArg)]) end, expand_bit_info(Meta, T, {size, [], [EArg]}, Types, EE); _ -> elixir_errors:compile_error(Meta, ?m(E, file), "duplicated size definition in bitstring") end; expand_bit_info(Meta, [{Expr, ExprMeta, Args}|T], Size, Types, E) when is_atom(Expr) -> case expand_bit_type(Expr, Args) of type -> {EArgs, EE} = elixir_exp:expand_args(Args, E), validate_bit_type_args(Meta, Expr, EArgs, EE), expand_bit_info(Meta, T, Size, [{Expr, [], EArgs}|Types], EE); none -> handle_unknown_bit_info(Meta, {Expr, ExprMeta, Args}, T, Size, Types, E) end; expand_bit_info(Meta, [Expr|_], _Size, _Types, E) -> elixir_errors:compile_error(Meta, ?m(E, file), "unknown bitstring specifier ~ts", ['Elixir.Kernel':inspect(Expr)]); expand_bit_info(Meta, [], Size, Types, _) -> [H|T] = case Size of default -> lists:reverse(Types); _ -> lists:reverse(Types, [Size]) end, lists:foldl(fun(I, Acc) -> {'-', Meta, [Acc, I]} end, H, T). expand_bit_type(binary, []) -> type; expand_bit_type(integer, []) -> type; expand_bit_type(float, []) -> type; expand_bit_type(bitstring, []) -> type; expand_bit_type(bytes, []) -> type; expand_bit_type(bits, []) -> type; expand_bit_type(utf8, []) -> type; expand_bit_type(utf16, []) -> type; expand_bit_type(utf32, []) -> type; expand_bit_type(signed, []) -> type; expand_bit_type(unsigned, []) -> type; expand_bit_type(big, []) -> type; expand_bit_type(little, []) -> type; expand_bit_type(native, []) -> type; expand_bit_type(unit, [_]) -> type; expand_bit_type(_, _) -> none. validate_bit_type_args(Meta, unit, [Unit], E) when not is_integer(Unit) -> elixir_errors:compile_error(Meta, ?m(E, file), "unit in bitstring expects an integer as argument, got: ~ts", ['Elixir.Macro':to_string(Unit)]); validate_bit_type_args(_Meta, _Expr, _Args, _E) -> ok. handle_unknown_bit_info(Meta, Expr, T, Size, Types, E) -> case 'Elixir.Macro':expand(Expr, elixir_env:linify({?line(Meta), E})) of Expr -> elixir_errors:compile_error(Meta, ?m(E, file), "unknown bitstring specifier ~ts", ['Elixir.Macro':to_string(Expr)]); Info -> expand_bit_info(Meta, unpack_bit_info(Info, []) ++ T, Size, Types, E) end. unpack_bit_info({'-', _, [H, T]}, Acc) -> unpack_bit_info(H, unpack_bit_info(T, Acc)); unpack_bit_info({'*', _, [{'_', _, Atom}, Unit]}, Acc) when is_atom(Atom) and is_integer(Unit) -> [{unit, [], [Unit]}|Acc]; unpack_bit_info({'*', _, [Size, Unit]}, Acc) when is_integer(Size) and is_integer(Unit) -> [{size, [], [Size]}, {unit, [], [Unit]}|Acc]; unpack_bit_info(Size, Acc) when is_integer(Size) -> [{size, [], [Size]}|Acc]; unpack_bit_info({Expr, Meta, Args}, Acc) when is_atom(Expr) -> ListArgs = if is_atom(Args) -> []; is_list(Args) -> Args end, [{Expr, Meta, ListArgs}|Acc]; unpack_bit_info(Other, Acc) -> [Other|Acc]. %% Translation has_size({bin, _, Elements}) -> not lists:any(fun({bin_element, _Line, _Expr, Size, Types}) -> (Types /= default) andalso (Size == default) andalso lists:any(fun(X) -> lists:member(X, Types) end, [bits, bytes, bitstring, binary]) end, Elements). translate(Meta, Args, S) -> case S#elixir_scope.context of match -> build_bitstr(fun elixir_translator:translate/2, Args, Meta, S); _ -> build_bitstr(fun(X, Acc) -> elixir_translator:translate_arg(X, Acc, S) end, Args, Meta, S) end. build_bitstr(Fun, Exprs, Meta, S) -> {Final, FinalS} = build_bitstr_each(Fun, Exprs, Meta, S, []), {{bin, ?line(Meta), lists:reverse(Final)}, FinalS}. build_bitstr_each(_Fun, [], _Meta, S, Acc) -> {Acc, S}; build_bitstr_each(Fun, [{'::', _, [H, V]}|T], Meta, S, Acc) -> {Size, Types} = extract_bit_info(V, S#elixir_scope{context=nil}), build_bitstr_each(Fun, T, Meta, S, Acc, H, Size, Types); build_bitstr_each(Fun, [H|T], Meta, S, Acc) -> build_bitstr_each(Fun, T, Meta, S, Acc, H, default, default). build_bitstr_each(Fun, T, Meta, S, Acc, H, default, Types) when is_binary(H) -> Element = case types_allow_splice(Types, []) of true -> %% See explanation in elixir_utils:elixir_to_erl/1 to know %% why we can simply convert the binary to a list. {bin_element, ?line(Meta), {string, 0, binary_to_list(H)}, default, default}; false -> case types_require_conversion(Types) of true -> {bin_element, ?line(Meta), {string, 0, elixir_utils:characters_to_list(H)}, default, Types}; false -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "invalid types for literal string in <<>>. " "Accepted types are: little, big, utf8, utf16, utf32, bits, bytes, binary, bitstring") end end, build_bitstr_each(Fun, T, Meta, S, [Element|Acc]); build_bitstr_each(_Fun, _T, Meta, S, _Acc, H, _Size, _Types) when is_binary(H) -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "size is not supported for literal string in <<>>"); build_bitstr_each(_Fun, _T, Meta, S, _Acc, H, _Size, _Types) when is_list(H); is_atom(H) -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "invalid literal ~ts in <<>>", ['Elixir.Macro':to_string(H)]); build_bitstr_each(Fun, T, Meta, S, Acc, H, Size, Types) -> {Expr, NS} = Fun(H, S), case Expr of {bin, _, Elements} -> case (Size == default) andalso types_allow_splice(Types, Elements) of true -> build_bitstr_each(Fun, T, Meta, NS, lists:reverse(Elements, Acc)); false -> build_bitstr_each(Fun, T, Meta, NS, [{bin_element, ?line(Meta), Expr, Size, Types}|Acc]) end; _ -> build_bitstr_each(Fun, T, Meta, NS, [{bin_element, ?line(Meta), Expr, Size, Types}|Acc]) end. types_require_conversion([End|T]) when End == little; End == big -> types_require_conversion(T); types_require_conversion([UTF|T]) when UTF == utf8; UTF == utf16; UTF == utf32 -> types_require_conversion(T); types_require_conversion([]) -> true; types_require_conversion(_) -> false. types_allow_splice([bytes], Elements) -> is_byte_size(Elements, 0); types_allow_splice([binary], Elements) -> is_byte_size(Elements, 0); types_allow_splice([bits], _) -> true; types_allow_splice([bitstring], _) -> true; types_allow_splice(default, _) -> true; types_allow_splice(_, _) -> false. is_byte_size([Element|T], Acc) -> case elem_size(Element) of {unknown, Unit} when Unit rem 8 == 0 -> is_byte_size(T, Acc); {unknown, _Unit} -> false; {Size, Unit} -> is_byte_size(T, Size*Unit + Acc) end; is_byte_size([], Size) -> Size rem 8 == 0. elem_size({bin_element, _, _, default, _}) -> {0, 0}; elem_size({bin_element, _, _, {integer, _, Size}, Types}) -> {Size, unit_size(Types, 1)}; elem_size({bin_element, _, _, _Size, Types}) -> {unknown, unit_size(Types, 1)}. unit_size([binary|T], _) -> unit_size(T, 8); unit_size([{unit, Size}|_], _) -> Size; unit_size([_|T], Guess) -> unit_size(T, Guess); unit_size([], Guess) -> Guess. %% Extra bitstring specifiers extract_bit_info({'-', _, [L, {size, _, [Size]}]}, S) -> {extract_bit_size(Size, S), extract_bit_type(L, [])}; extract_bit_info({size, _, [Size]}, S) -> {extract_bit_size(Size, S), []}; extract_bit_info(L, _S) -> {default, extract_bit_type(L, [])}. extract_bit_size(Size, S) -> {TSize, _} = elixir_translator:translate(Size, S), TSize. extract_bit_type({'-', _, [L, R]}, Acc) -> extract_bit_type(L, extract_bit_type(R, Acc)); extract_bit_type({unit, _, [Arg]}, Acc) -> [{unit, Arg}|Acc]; extract_bit_type({Other, _, []}, Acc) -> [Other|Acc]. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_bootstrap.erl000066400000000000000000000033321254730255300240440ustar00rootroot00000000000000%% An Erlang module that behaves like an Elixir module %% used for bootstraping. -module(elixir_bootstrap). -export(['MACRO-def'/2, 'MACRO-def'/3, 'MACRO-defp'/3, 'MACRO-defmodule'/3, 'MACRO-defmacro'/2, 'MACRO-defmacro'/3, 'MACRO-defmacrop'/3, 'MACRO-@'/2, '__info__'/1]). -define(kernel, 'Elixir.Kernel'). %% Mock out @ to be a no-op unless Kernel is defined. 'MACRO-@'(Caller, Tree) -> unless_loaded('MACRO-@', [Caller, Tree], fun() -> nil end). 'MACRO-def'(Caller, Call) -> 'MACRO-def'(Caller, Call, nil). 'MACRO-def'(Caller, Call, Expr) -> define(Caller, def, Call, Expr). 'MACRO-defp'(Caller, Call, Expr) -> define(Caller, defp, Call, Expr). 'MACRO-defmacro'(Caller, Call) -> 'MACRO-defmacro'(Caller, Call, nil). 'MACRO-defmacro'(Caller, Call, Expr) -> define(Caller, defmacro, Call, Expr). 'MACRO-defmacrop'(Caller, Call, Expr) -> define(Caller, defmacrop, Call, Expr). 'MACRO-defmodule'(_Caller, Alias, [{do, Block}]) -> {Escaped, _} = elixir_quote:escape(Block, false), Args = [Alias, Escaped, [], env()], {{'.', [], [elixir_module, compile]}, [], Args}. '__info__'(functions) -> []; '__info__'(macros) -> [{'@', 1}, {def, 1}, {def, 2}, {defmacro, 1}, {defmacro, 2}, {defmacrop, 2}, {defmodule, 2}, {defp, 2}]. define({Line, E}, Kind, Call, Expr) -> {EscapedCall, UC} = elixir_quote:escape(Call, true), {EscapedExpr, UE} = elixir_quote:escape(Expr, true), Args = [Line, Kind, not(UC or UE), EscapedCall, EscapedExpr, elixir_locals:cache_env(E)], {{'.', [], [elixir_def, store_definition]}, [], Args}. unless_loaded(Fun, Args, Callback) -> case code:is_loaded(?kernel) of {_, _} -> apply(?kernel, Fun, Args); false -> Callback() end. env() -> {'__ENV__', [], nil}.elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_clauses.erl000066400000000000000000000201231254730255300234630ustar00rootroot00000000000000%% Handle code related to args, guard and -> matching for case, %% fn, receive and friends. try is handled in elixir_try. -module(elixir_clauses). -export([match/3, clause/7, clauses/4, guards/4, get_pairs/3, get_pairs/4, extract_splat_guards/1, extract_guards/1]). -include("elixir.hrl"). %% Get pairs from a clause. get_pairs(Key, Clauses, As) -> get_pairs(Key, Clauses, As, false). get_pairs(Key, Clauses, As, AllowNil) -> case lists:keyfind(Key, 1, Clauses) of {Key, Pairs} when is_list(Pairs) -> [{As, Meta, Left, Right} || {'->', Meta, [Left, Right]} <- Pairs]; {Key, nil} when AllowNil -> []; false -> [] end. %% Translate matches match(Fun, Args, #elixir_scope{context=Context, match_vars=MatchVars, backup_vars=BackupVars, vars=Vars} = S) when Context /= match -> {Result, NewS} = match(Fun, Args, S#elixir_scope{context=match, match_vars=ordsets:new(), backup_vars=Vars}), {Result, NewS#elixir_scope{context=Context, match_vars=MatchVars, backup_vars=BackupVars}}; match(Fun, Args, S) -> Fun(Args, S). %% Translate clauses with args, guards and expressions clause(Line, Fun, Args, Expr, Guards, Return, S) when is_integer(Line) -> {TArgs, SA} = match(Fun, Args, S#elixir_scope{extra_guards=[]}), {TExpr, SE} = elixir_translator:translate_block(Expr, Return, SA#elixir_scope{extra_guards=nil}), Extra = SA#elixir_scope.extra_guards, TGuards = guards(Line, Guards, Extra, SA), {{clause, Line, TArgs, TGuards, unblock(TExpr)}, SE}. % Translate/Extract guards from the given expression. guards(Line, Guards, Extra, S) -> SG = S#elixir_scope{context=guard, extra_guards=nil}, case Guards of [] -> case Extra of [] -> []; _ -> [Extra] end; _ -> [translate_guard(Line, Guard, Extra, SG) || Guard <- Guards] end. translate_guard(Line, Guard, Extra, S) -> [element(1, elixir_translator:translate(elixir_quote:linify(Line, Guard), S))|Extra]. extract_guards({'when', _, [Left, Right]}) -> {Left, extract_or_guards(Right)}; extract_guards(Else) -> {Else, []}. extract_or_guards({'when', _, [Left, Right]}) -> [Left|extract_or_guards(Right)]; extract_or_guards(Term) -> [Term]. % Extract guards when multiple left side args are allowed. extract_splat_guards([{'when', _, [_, _|_] = Args}]) -> {Left, Right} = elixir_utils:split_last(Args), {Left, extract_or_guards(Right)}; extract_splat_guards(Else) -> {Else, []}. % Function for translating macros with match style like case and receive. clauses(Meta, Clauses, Return, #elixir_scope{export_vars=CV} = S) -> {TC, TS} = do_clauses(Meta, Clauses, Return, S#elixir_scope{export_vars=[]}), {TC, TS#elixir_scope{export_vars=elixir_scope:merge_opt_vars(CV, TS#elixir_scope.export_vars)}}. do_clauses(_Meta, [], _Return, S) -> {[], S}; do_clauses(Meta, DecoupledClauses, Return, S) -> % Transform tree just passing the variables counter forward % and storing variables defined inside each clause. Transformer = fun(X, {SAcc, VAcc}) -> {TX, TS} = each_clause(Meta, X, Return, SAcc), {TX, {elixir_scope:mergec(S, TS), [TS#elixir_scope.export_vars|VAcc]}} end, {TClauses, {TS, ReverseCV}} = lists:mapfoldl(Transformer, {S, []}, DecoupledClauses), % Now get all the variables defined inside each clause CV = lists:reverse(ReverseCV), AllVars = lists:foldl(fun elixir_scope:merge_vars/2, [], CV), % Create a new scope that contains a list of all variables % defined inside all the clauses. It returns this new scope and % a list of tuples where the first element is the variable name, % the second one is the new pointer to the variable and the third % is the old pointer. {FinalVars, FS} = lists:mapfoldl(fun({Key, Val}, Acc) -> normalize_vars(Key, Val, Acc) end, TS, AllVars), % Expand all clauses by adding a match operation at the end % that defines variables missing in one clause to the others. expand_clauses(?line(Meta), TClauses, CV, FinalVars, [], FS). expand_clauses(Line, [Clause|T], [ClauseVars|V], FinalVars, Acc, S) -> case generate_match_vars(FinalVars, ClauseVars, [], []) of {[], []} -> expand_clauses(Line, T, V, FinalVars, [Clause|Acc], S); {Left, Right} -> MatchExpr = generate_match(Line, Left, Right), ClauseExprs = element(5, Clause), [Final|RawClauseExprs] = lists:reverse(ClauseExprs), % If the last sentence has a match clause, we need to assign its value % in the variable list. If not, we insert the variable list before the % final clause in order to keep it tail call optimized. {FinalClauseExprs, FS} = case has_match_tuple(Final) of true -> case Final of {match, _, {var, _, UserVarName} = UserVar, _} when UserVarName /= '_' -> {[UserVar, MatchExpr, Final|RawClauseExprs], S}; _ -> {VarName, _, SS} = elixir_scope:build_var('_', S), StorageVar = {var, Line, VarName}, StorageExpr = {match, Line, StorageVar, Final}, {[StorageVar, MatchExpr, StorageExpr|RawClauseExprs], SS} end; false -> {[Final, MatchExpr|RawClauseExprs], S} end, FinalClause = setelement(5, Clause, lists:reverse(FinalClauseExprs)), expand_clauses(Line, T, V, FinalVars, [FinalClause|Acc], FS) end; expand_clauses(_Line, [], [], _FinalVars, Acc, S) -> {lists:reverse(Acc), S}. % Handle each key/value clause pair and translate them accordingly. each_clause(Export, {match, Meta, [Condition], Expr}, Return, S) -> Fun = wrap_export_fun(Export, fun elixir_translator:translate_args/2), {Arg, Guards} = extract_guards(Condition), clause(?line(Meta), Fun, [Arg], Expr, Guards, Return, S); each_clause(Export, {expr, Meta, [Condition], Expr}, Return, S) -> {TCondition, SC} = (wrap_export_fun(Export, fun elixir_translator:translate/2))(Condition, S), {TExpr, SB} = elixir_translator:translate_block(Expr, Return, SC), {{clause, ?line(Meta), [TCondition], [], unblock(TExpr)}, SB}. wrap_export_fun(Meta, Fun) -> case lists:keyfind(export_head, 1, Meta) of {export_head, true} -> Fun; _ -> fun(Args, S) -> {TArgs, TS} = Fun(Args, S), {TArgs, TS#elixir_scope{export_vars = S#elixir_scope.export_vars}} end end. % Check if the given expression is a match tuple. % This is a small optimization to allow us to change % existing assignments instead of creating new ones every time. has_match_tuple({'receive', _, _, _, _}) -> true; has_match_tuple({'receive', _, _}) -> true; has_match_tuple({'case', _, _, _}) -> true; has_match_tuple({match, _, _, _}) -> true; has_match_tuple({'fun', _, {clauses, _}}) -> false; has_match_tuple(H) when is_tuple(H) -> has_match_tuple(tuple_to_list(H)); has_match_tuple(H) when is_list(H) -> lists:any(fun has_match_tuple/1, H); has_match_tuple(_) -> false. % Normalize the given var between clauses % by picking one value as reference and retrieving % its previous value. normalize_vars(Key, Value, #elixir_scope{vars=Vars, export_vars=ClauseVars} = S) -> VS = S#elixir_scope{ vars=orddict:store(Key, Value, Vars), export_vars=orddict:store(Key, Value, ClauseVars) }, Expr = case orddict:find(Key, Vars) of {ok, {PreValue, _}} -> {var, 0, PreValue}; error -> {atom, 0, nil} end, {{Key, Value, Expr}, VS}. % Generate match vars by checking if they were updated % or not and assigning the previous value. generate_match_vars([{Key, Value, Expr}|T], ClauseVars, Left, Right) -> case orddict:find(Key, ClauseVars) of {ok, Value} -> generate_match_vars(T, ClauseVars, Left, Right); {ok, Clause} -> generate_match_vars(T, ClauseVars, [{var, 0, element(1, Value)}|Left], [{var, 0, element(1, Clause)}|Right]); error -> generate_match_vars(T, ClauseVars, [{var, 0, element(1, Value)}|Left], [Expr|Right]) end; generate_match_vars([], _ClauseVars, Left, Right) -> {Left, Right}. generate_match(Line, [Left], [Right]) -> {match, Line, Left, Right}; generate_match(Line, LeftVars, RightVars) -> {match, Line, {tuple, Line, LeftVars}, {tuple, Line, RightVars}}. unblock({'block', _, Exprs}) -> Exprs; unblock(Exprs) -> [Exprs]. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_code_server.erl000066400000000000000000000120611254730255300243260ustar00rootroot00000000000000-module(elixir_code_server). -export([call/1, cast/1]). -export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -behaviour(gen_server). -define(timeout, 30000). -record(elixir_code_server, { loaded=[], mod_pool={[], 0}, mod_ets=dict:new(), compilation_status=[] }). call(Args) -> gen_server:call(?MODULE, Args, ?timeout). cast(Args) -> gen_server:cast(?MODULE, Args). %% Callbacks start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []). init(ok) -> %% We attempt to load those modules here so throughout %% the codebase we can avoid code:is_loaded/1 checks. _ = code:ensure_loaded('Elixir.Macro.Env'), %% The table where we store module definitions _ = ets:new(elixir_modules, [set, protected, named_table, {read_concurrency, true}]), {ok, #elixir_code_server{}}. handle_call({defmodule, Pid, Tuple}, _From, Config) -> {Ref, New} = defmodule(Pid, Tuple, Config), {reply, Ref, New}; handle_call({undefmodule, Ref}, _From, Config) -> {reply, ok, undefmodule(Ref, Config)}; handle_call({acquire, Path}, From, Config) -> Current = Config#elixir_code_server.loaded, case orddict:find(Path, Current) of {ok, true} -> {reply, loaded, Config}; {ok, {Ref, List}} when is_list(List), is_reference(Ref) -> Queued = orddict:store(Path, {Ref, [From|List]}, Current), {reply, {queued, Ref}, Config#elixir_code_server{loaded=Queued}}; error -> Queued = orddict:store(Path, {make_ref(), []}, Current), {reply, proceed, Config#elixir_code_server{loaded=Queued}} end; handle_call(loaded, _From, Config) -> {reply, [F || {F, true} <- Config#elixir_code_server.loaded], Config}; handle_call({compilation_status, CompilerPid}, _From, Config) -> CompilationStatusList = Config#elixir_code_server.compilation_status, CompilationStatusListNew = orddict:erase(CompilerPid, CompilationStatusList), CompilationStatus = orddict:fetch(CompilerPid, CompilationStatusList), {reply, CompilationStatus, Config#elixir_code_server{compilation_status=CompilationStatusListNew}}; handle_call(retrieve_module_name, _From, Config) -> case Config#elixir_code_server.mod_pool of {[H|T], Counter} -> {reply, module_tuple(H), Config#elixir_code_server{mod_pool={T, Counter}}}; {[], Counter} -> {reply, module_tuple(Counter), Config#elixir_code_server{mod_pool={[], Counter+1}}} end; handle_call(Request, _From, Config) -> {stop, {badcall, Request}, Config}. handle_cast({register_warning, CompilerPid}, Config) -> CompilationStatusCurrent = Config#elixir_code_server.compilation_status, CompilationStatusNew = orddict:store(CompilerPid, error, CompilationStatusCurrent), CompilerOptions = elixir_config:get(compiler_options), case orddict:find(warnings_as_errors, CompilerOptions) of {ok, true} -> {noreply, Config#elixir_code_server{compilation_status=CompilationStatusNew}}; _ -> {noreply, Config} end; handle_cast({reset_warnings, CompilerPid}, Config) -> CompilationStatusCurrent = Config#elixir_code_server.compilation_status, CompilationStatusNew = orddict:store(CompilerPid, ok, CompilationStatusCurrent), {noreply, Config#elixir_code_server{compilation_status=CompilationStatusNew}}; handle_cast({loaded, Path}, Config) -> Current = Config#elixir_code_server.loaded, case orddict:find(Path, Current) of {ok, true} -> {noreply, Config}; {ok, {Ref, List}} when is_list(List), is_reference(Ref) -> _ = [Pid ! {elixir_code_server, Ref, loaded} || {Pid, _Tag} <- lists:reverse(List)], Done = orddict:store(Path, true, Current), {noreply, Config#elixir_code_server{loaded=Done}}; error -> Done = orddict:store(Path, true, Current), {noreply, Config#elixir_code_server{loaded=Done}} end; handle_cast({unload_files, Files}, Config) -> Current = Config#elixir_code_server.loaded, Unloaded = lists:foldl(fun(File, Acc) -> orddict:erase(File, Acc) end, Current, Files), {noreply, Config#elixir_code_server{loaded=Unloaded}}; handle_cast({return_module_name, H}, #elixir_code_server{mod_pool={T, Counter}} = Config) -> {noreply, Config#elixir_code_server{mod_pool={[H|T], Counter}}}; handle_cast(Request, Config) -> {stop, {badcast, Request}, Config}. handle_info({'DOWN', Ref, process, _Pid, _Reason}, Config) -> {noreply, undefmodule(Ref, Config)}; handle_info(_Msg, Config) -> {noreply, Config}. terminate(_Reason, _Config) -> ok. code_change(_Old, Config, _Extra) -> {ok, Config}. module_tuple(I) -> {list_to_atom("elixir_compiler_" ++ integer_to_list(I)), I}. defmodule(Pid, Tuple, #elixir_code_server{mod_ets=ModEts} = Config) -> ets:insert(elixir_modules, Tuple), Ref = erlang:monitor(process, Pid), Mod = erlang:element(1, Tuple), {Ref, Config#elixir_code_server{mod_ets=dict:store(Ref, Mod, ModEts)}}. undefmodule(Ref, #elixir_code_server{mod_ets=ModEts} = Config) -> case dict:find(Ref, ModEts) of {ok, Mod} -> ets:delete(elixir_modules, Mod), Config#elixir_code_server{mod_ets=dict:erase(Ref, ModEts)}; error -> Config end. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_compiler.erl000066400000000000000000000215121254730255300236410ustar00rootroot00000000000000-module(elixir_compiler). -export([get_opt/1, string/2, quoted/2, file/1, file/2, file_to_path/2]). -export([core/0, module/4, eval_forms/3]). -include("elixir.hrl"). %% Public API get_opt(Key) -> Dict = elixir_config:get(compiler_options), case lists:keyfind(Key, 1, Dict) of false -> false; {Key, Value} -> Value end. %% Compilation entry points. string(Contents, File) when is_list(Contents), is_binary(File) -> string(Contents, File, nil). string(Contents, File, Dest) -> Forms = elixir:'string_to_quoted!'(Contents, 1, File, []), quoted(Forms, File, Dest). quoted(Forms, File) when is_binary(File) -> quoted(Forms, File, nil). quoted(Forms, File, Dest) -> Previous = get(elixir_compiled), try put(elixir_compiled, []), elixir_lexical:run(File, Dest, fun (Pid) -> Env = elixir:env_for_eval([{line, 1}, {file, File}]), eval_forms(Forms, [], Env#{lexical_tracker := Pid}) end), lists:reverse(get(elixir_compiled)) after put(elixir_compiled, Previous) end. file(Relative) when is_binary(Relative) -> file(Relative, nil). file(Relative, Dest) -> File = filename:absname(Relative), {ok, Bin} = file:read_file(File), string(elixir_utils:characters_to_list(Bin), File, case Dest of nil -> Dest; _ -> filename:absname(Dest) end). file_to_path(File, Dest) when is_binary(File), is_binary(Dest) -> Comp = file(File, Dest), Abs = filename:absname(Dest), _ = [binary_to_path(X, Abs) || X <- Comp], Comp. %% Evaluation eval_forms(Forms, Vars, E) -> case (?m(E, module) == nil) andalso allows_fast_compilation(Forms) of true -> eval_compilation(Forms, Vars, E); false -> code_loading_compilation(Forms, Vars, E) end. eval_compilation(Forms, Vars, E) -> Binding = [{Key, Value} || {_Name, _Kind, Key, Value} <- Vars], {Result, _Binding, EE, _S} = elixir:eval_forms(Forms, Binding, E), {Result, EE}. code_loading_compilation(Forms, Vars, #{line := Line} = E) -> Dict = [{{Name, Kind}, {Value, 0}} || {Name, Kind, Value, _} <- Vars], S = elixir_env:env_to_scope_with_vars(E, Dict), {Expr, EE, _S} = elixir:quoted_to_erl(Forms, E, S), {Module, I} = retrieve_module_name(), Fun = code_fun(?m(E, module)), Form = code_mod(Fun, Expr, Line, ?m(E, file), Module, Vars), Args = list_to_tuple([V || {_, _, _, V} <- Vars]), %% Pass {native, false} to speed up bootstrap %% process when native is set to true AllOpts = options(), FinalOpts = AllOpts -- [native, warn_missing_spec], inner_module(Form, FinalOpts, true, E, fun(_, Binary) -> %% If we have labeled locals, anonymous functions %% were created and therefore we cannot ditch the %% module Purgeable = case beam_lib:chunks(Binary, [labeled_locals]) of {ok, {_, [{labeled_locals, []}]}} -> true; _ -> false end, dispatch_loaded(Module, Fun, Args, Purgeable, I, EE) end). options() -> case elixir_config:get(erl_compiler_options) of nil -> elixir_config:update(erl_compiler_options, fun options/1); Opts -> Opts end. options(nil) -> Key = "ERL_COMPILER_OPTIONS", case os:getenv(Key) of false -> []; Str when is_list(Str) -> case erl_scan:string(Str) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of {ok, List} when is_list(List) -> List; {ok, Term} -> [Term]; {error, _Reason} -> io:format("Ignoring bad term in ~ts\n", [Key]), [] end; {error, {_, _, _Reason}, _} -> io:format("Ignoring bad term in ~ts\n", [Key]), [] end end; options(Opts) -> Opts. dispatch_loaded(Module, Fun, Args, Purgeable, I, E) -> Res = Module:Fun(Args), code:delete(Module), if Purgeable -> code:purge(Module), return_module_name(I); true -> ok end, {Res, E}. code_fun(nil) -> '__FILE__'; code_fun(_) -> '__MODULE__'. code_mod(Fun, Expr, Line, File, Module, Vars) when is_binary(File), is_integer(Line) -> Tuple = {tuple, Line, [{var, Line, K} || {_, _, K, _} <- Vars]}, Relative = elixir_utils:relative_to_cwd(File), [ {attribute, Line, file, {elixir_utils:characters_to_list(Relative), 1}}, {attribute, Line, module, Module}, {attribute, Line, export, [{Fun, 1}, {'__RELATIVE__', 0}]}, {function, Line, Fun, 1, [ {clause, Line, [Tuple], [], [Expr]} ]}, {function, Line, '__RELATIVE__', 0, [ {clause, Line, [], [], [elixir_utils:elixir_to_erl(Relative)]} ]} ]. retrieve_module_name() -> elixir_code_server:call(retrieve_module_name). return_module_name(I) -> elixir_code_server:cast({return_module_name, I}). allows_fast_compilation({'__block__', _, Exprs}) -> lists:all(fun allows_fast_compilation/1, Exprs); allows_fast_compilation({defmodule, _, _}) -> true; allows_fast_compilation(_) -> false. %% INTERNAL API %% Compile the module by forms based on the scope information %% executes the callback in case of success. This automatically %% handles errors and warnings. Used by this module and elixir_module. module(Forms, Opts, E, Callback) -> Final = case (get_opt(debug_info) == true) orelse lists:member(debug_info, Opts) of true -> [debug_info] ++ options(); false -> options() end, inner_module(Forms, Final, false, E, Callback). inner_module(Forms, Options, Bootstrap, #{file := File} = E, Callback) when is_list(Forms), is_list(Options), is_boolean(Bootstrap), is_function(Callback) -> Source = elixir_utils:characters_to_list(File), case compile:noenv_forms([no_auto_import()|Forms], [return, {source, Source}|Options]) of {ok, Module, Binary, Warnings} -> format_warnings(Bootstrap, Warnings), {module, Module} = code:load_binary(Module, beam_location(E), Binary), Callback(Module, Binary); {error, Errors, Warnings} -> format_warnings(Bootstrap, Warnings), format_errors(Errors) end. beam_location(#{module := nil}) -> in_memory; beam_location(#{lexical_tracker := Pid, module := Module}) -> case elixir_lexical:dest(Pid) of nil -> in_memory; Dest -> filename:join(elixir_utils:characters_to_list(Dest), atom_to_list(Module) ++ ".beam") end. no_auto_import() -> {attribute, 0, compile, no_auto_import}. %% CORE HANDLING core() -> {ok, _} = application:ensure_all_started(elixir), New = orddict:from_list([{docs, false}, {internal, true}]), Merge = fun(_, _, Value) -> Value end, Update = fun(Old) -> orddict:merge(Merge, Old, New) end, _ = elixir_config:update(compiler_options, Update), [core_file(File) || File <- core_main()]. core_file(File) -> try Lists = file(File), _ = [binary_to_path(X, "lib/elixir/ebin") || X <- Lists], io:format("Compiled ~ts~n", [File]) catch Kind:Reason -> io:format("~p: ~p~nstacktrace: ~p~n", [Kind, Reason, erlang:get_stacktrace()]), erlang:halt(1) end. core_main() -> [<<"lib/elixir/lib/kernel.ex">>, <<"lib/elixir/lib/macro/env.ex">>, <<"lib/elixir/lib/keyword.ex">>, <<"lib/elixir/lib/module.ex">>, <<"lib/elixir/lib/list.ex">>, <<"lib/elixir/lib/macro.ex">>, <<"lib/elixir/lib/code.ex">>, <<"lib/elixir/lib/module/locals_tracker.ex">>, <<"lib/elixir/lib/kernel/def.ex">>, <<"lib/elixir/lib/kernel/typespec.ex">>, <<"lib/elixir/lib/behaviour.ex">>, <<"lib/elixir/lib/exception.ex">>, <<"lib/elixir/lib/protocol.ex">>, <<"lib/elixir/lib/stream/reducers.ex">>, <<"lib/elixir/lib/enum.ex">>, <<"lib/elixir/lib/inspect/algebra.ex">>, <<"lib/elixir/lib/inspect.ex">>, <<"lib/elixir/lib/range.ex">>, <<"lib/elixir/lib/regex.ex">>, <<"lib/elixir/lib/string.ex">>, <<"lib/elixir/lib/string/chars.ex">>, <<"lib/elixir/lib/io.ex">>, <<"lib/elixir/lib/path.ex">>, <<"lib/elixir/lib/file.ex">>, <<"lib/elixir/lib/system.ex">>, <<"lib/elixir/lib/kernel/cli.ex">>, <<"lib/elixir/lib/kernel/error_handler.ex">>, <<"lib/elixir/lib/kernel/parallel_compiler.ex">>, <<"lib/elixir/lib/kernel/lexical_tracker.ex">>]. binary_to_path({ModuleName, Binary}, CompilePath) -> Path = filename:join(CompilePath, atom_to_list(ModuleName) ++ ".beam"), case file:write_file(Path, Binary) of ok -> Path; {error, Reason} -> error('Elixir.File.Error':exception([{action, "write to"}, {path, Path}, {reason, Reason}])) end. %% ERROR HANDLING format_errors([]) -> exit({nocompile, "compilation failed but no error was raised"}); format_errors(Errors) -> lists:foreach(fun ({File, Each}) -> BinFile = elixir_utils:characters_to_binary(File), lists:foreach(fun(Error) -> elixir_errors:handle_file_error(BinFile, Error) end, Each) end, Errors). format_warnings(Bootstrap, Warnings) -> lists:foreach(fun ({File, Each}) -> BinFile = elixir_utils:characters_to_binary(File), lists:foreach(fun(Warning) -> elixir_errors:handle_file_warning(Bootstrap, BinFile, Warning) end, Each) end, Warnings). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_config.erl000066400000000000000000000027731254730255300233040ustar00rootroot00000000000000-module(elixir_config). -compile({no_auto_import, [get/1]}). -export([new/1, delete/1, put/2, get/1, update/2, get_and_put/2]). -export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]). -behaviour(gen_server). %% public api new(Opts) -> Tab = ets:new(?MODULE, [named_table, public, {read_concurrency, true}]), true = ets:insert_new(?MODULE, Opts), Tab. delete(?MODULE) -> ets:delete(?MODULE). put(Key, Value) -> gen_server:call(?MODULE, {put, Key, Value}). get(Key) -> case ets:lookup(?MODULE, Key) of [{_, Value}] -> Value; [] -> nil end. update(Key, Fun) -> gen_server:call(?MODULE, {update, Key, Fun}). get_and_put(Key, Value) -> gen_server:call(?MODULE, {get_and_put, Key, Value}). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, ?MODULE, []). %% gen_server api init(Tab) -> %% Ets table must be writable public = ets:info(Tab, protection), {ok, Tab}. handle_call({put, Key, Value}, _From, Tab) -> ets:insert(Tab, {Key, Value}), {reply, ok, Tab}; handle_call({update, Key, Fun}, _From, Tab) -> Value = Fun(get(Key)), ets:insert(Tab, {Key, Value}), {reply, Value, Tab}; handle_call({get_and_put, Key, Value}, _From, Tab) -> OldValue = get(Key), ets:insert(Tab, {Key, Value}), {reply, OldValue, Tab}. handle_cast(Cast, Tab) -> {stop, {bad_cast, Cast}, Tab}. handle_info(_Msg, Tab) -> {noreply, Tab}. code_change(_OldVsn, Tab, _Extra) -> {ok, Tab}. terminate(_Reason, _Tab) -> ok. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_counter.erl000066400000000000000000000015451254730255300235120ustar00rootroot00000000000000-module(elixir_counter). -export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, next/0]). -behaviour(gen_server). -define(timeout, 30000). %% 30 seconds -define(limit, 4294967295). %% 2^32 - 1 next() -> gen_server:call(?MODULE, next, ?timeout). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, 0, []). init(Counter) -> {ok, Counter}. handle_call(next, _From, Counter) -> {reply, Counter, bump(Counter)}; handle_call(Request, _From, Counter) -> {stop, {badcall, Request}, Counter}. handle_cast(Request, Counter) -> {stop, {badcast, Request}, Counter}. handle_info(_Request, Counter) -> {noreply, Counter}. terminate(_Reason, _Counter) -> ok. code_change(_Old, Counter, _Extra) -> {ok, Counter}. bump(Counter) when Counter < ?limit -> Counter + 1; bump(_Counter) -> 0. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_def.erl000066400000000000000000000424341254730255300225730ustar00rootroot00000000000000% Holds the logic responsible for function definitions (def(p) and defmacro(p)). -module(elixir_def). -export([setup/1, reset_last/1, lookup_definition/2, delete_definition/2, store_definition/6, unwrap_definitions/2, store_each/7, format_error/1]). -include("elixir.hrl"). -define(last_def, {elixir, last_def}). -define(attr, {elixir, def_table}). -define(clauses_attr, {elixir, clauses_table}). %% Table management functions. Called internally. setup(Module) -> reset_last(Module), ok. reset_last(Module) -> ets:insert(elixir_module:data_table(Module), {?last_def, []}). lookup_definition(Module, Tuple) -> case ets:lookup(elixir_module:defs_table(Module), Tuple) of [Result] -> CTable = elixir_module:clas_table(Module), {Result, [Clause || {_, Clause} <- ets:lookup(CTable, Tuple)]}; _ -> false end. delete_definition(Module, Tuple) -> ets:delete(elixir_module:defs_table(Module), Tuple), ets:delete(elixir_module:clas_table(Module), Tuple). % Invoked by the wrap definition with the function abstract tree. % Each function is then added to the function table. store_definition(Line, Kind, CheckClauses, Call, Body, Pos) -> E = (elixir_locals:get_cached_env(Pos))#{line := Line}, {NameAndArgs, Guards} = elixir_clauses:extract_guards(Call), {Name, Args} = case NameAndArgs of {N, _, A} when is_atom(N), is_atom(A) -> {N, []}; {N, _, A} when is_atom(N), is_list(A) -> {N, A}; _ -> elixir_errors:form_error([{line, Line}], ?m(E, file), ?MODULE, {invalid_def, Kind, NameAndArgs}) end, %% Now that we have verified the call format, %% extract meta information like file and context. {_, Meta, _} = Call, DoCheckClauses = (not lists:keymember(context, 1, Meta)) andalso (CheckClauses), %% Check if there is a file information in the definition. %% If so, we assume this come from another source and %% we need to linify taking into account keep line numbers. {Location, Key} = case elixir_utils:meta_location(Meta) of {_, _} = KeepLocation -> {KeepLocation, keep}; nil -> {nil, line} end, LinifyArgs = elixir_quote:linify(Line, Key, Args), LinifyGuards = elixir_quote:linify(Line, Key, Guards), LinifyBody = elixir_quote:linify(Line, Key, Body), assert_no_aliases_name(Line, Name, Args, E), assert_valid_name(Line, Kind, Name, Args, E), store_definition(Line, Kind, DoCheckClauses, Name, LinifyArgs, LinifyGuards, LinifyBody, Location, E). store_definition(Line, Kind, CheckClauses, Name, Args, Guards, Body, KeepLocation, #{module := Module} = ER) -> Arity = length(Args), Tuple = {Name, Arity}, E = ER#{function := Tuple}, elixir_locals:record_definition(Tuple, Kind, Module), Location = retrieve_location(KeepLocation, Module), {Function, Defaults, Super} = translate_definition(Kind, Line, Name, Args, Guards, Body, E), run_on_definition_callbacks(Kind, Line, Module, Name, Args, Guards, expr_from_body(Line, Body), E), DefaultsLength = length(Defaults), elixir_locals:record_defaults(Tuple, Kind, Module, DefaultsLength), File = ?m(E, file), compile_super(Module, Super, E), check_previous_defaults(Line, Module, Name, Arity, Kind, DefaultsLength, E), store_each(CheckClauses, Kind, File, Location, Module, DefaultsLength, Function), [store_each(false, Kind, File, Location, Module, 0, default_function_for(Kind, Name, Default)) || Default <- Defaults], make_struct_available(Kind, Module, Name, Args), {Name, Arity}. %% @on_definition run_on_definition_callbacks(Kind, Line, Module, Name, Args, Guards, Expr, E) -> case elixir_compiler:get_opt(internal) of true -> ok; _ -> Env = elixir_env:linify({Line, E}), Callbacks = 'Elixir.Module':get_attribute(Module, on_definition), _ = [Mod:Fun(Env, Kind, Name, Args, Guards, Expr) || {Mod, Fun} <- Callbacks], ok end. make_struct_available(def, Module, '__struct__', []) -> case erlang:get(elixir_compiler_pid) of undefined -> ok; Pid -> Pid ! {struct_available, Module}, ok end; make_struct_available(_, _, _, _) -> ok. %% Retrieve location from meta file (if Key == keep) %% or @file, otherwise nil retrieve_location(Location, Module) -> case get_location_attribute(Module) of nil when is_tuple(Location) -> {File, Line} = Location, {normalize_location(File), Line}; nil -> nil; File when is_binary(File) -> 'Elixir.Module':delete_attribute(Module, file), {normalize_location(File), 0}; {File, Line} when is_binary(File) andalso is_integer(Line) -> 'Elixir.Module':delete_attribute(Module, file), {normalize_location(File), Line} end. get_location_attribute(Module) -> case elixir_compiler:get_opt(internal) of true -> nil; false -> 'Elixir.Module':get_attribute(Module, file) end. normalize_location(File) -> elixir_utils:characters_to_list(elixir_utils:relative_to_cwd(File)). %% Compile super compile_super(Module, true, #{function := Function}) -> elixir_def_overridable:super(Module, Function); compile_super(_Module, _, _E) -> ok. %% Translate the given call and expression given %% and then store it in memory. translate_definition(Kind, Line, Name, Args, Guards, Body, E) when is_integer(Line) -> Arity = length(Args), {EArgs, EGuards, EBody, _} = elixir_exp_clauses:def(fun elixir_def_defaults:expand/2, Args, Guards, expr_from_body(Line, Body), E), Body == nil andalso check_args_for_bodyless_clause(Line, EArgs, E), S = elixir_env:env_to_scope(E), {Unpacked, Defaults} = elixir_def_defaults:unpack(Kind, Name, EArgs, S), {Clauses, Super} = translate_clause(Body, Line, Kind, Unpacked, EGuards, EBody, S), Function = {function, Line, Name, Arity, Clauses}, {Function, Defaults, Super}. translate_clause(nil, _Line, _Kind, _Args, [], _Body, _S) -> {[], false}; translate_clause(nil, Line, Kind, _Args, _Guards, _Body, #elixir_scope{file=File}) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {missing_do, Kind}); translate_clause(_, Line, Kind, Args, Guards, Body, S) -> {TClause, TS} = elixir_clauses:clause(Line, fun elixir_translator:translate_args/2, Args, Body, Guards, true, S), FClause = case is_macro(Kind) of true -> FArgs = {var, Line, '_@CALLER'}, MClause = setelement(3, TClause, [FArgs|element(3, TClause)]), case TS#elixir_scope.caller of true -> FBody = {'match', Line, {'var', Line, '__CALLER__'}, elixir_utils:erl_call(Line, elixir_env, linify, [{var, Line, '_@CALLER'}]) }, setelement(5, MClause, [FBody|element(5, TClause)]); false -> MClause end; false -> TClause end, {[FClause], TS#elixir_scope.super}. expr_from_body(_Line, nil) -> nil; expr_from_body(_Line, [{do, Expr}]) -> Expr; expr_from_body(Line, Else) -> {'try', [{line, Line}], [Else]}. is_macro(defmacro) -> true; is_macro(defmacrop) -> true; is_macro(_) -> false. % Unwrap the functions stored in the functions table. % It returns a list of all functions to be exported, plus the macros, % and the body of all functions. unwrap_definitions(File, Module) -> Table = elixir_module:defs_table(Module), CTable = elixir_module:clas_table(Module), {All, Private} = unwrap_definition(ets:tab2list(Table), File, Module, CTable, [], []), Unreachable = elixir_locals:warn_unused_local(File, Module, Private), split_definition(All, Unreachable, [], [], [], [], [], {[], []}). unwrap_definition([Fun|T], File, Module, CTable, All, Private) -> {Tuple, Kind, Line, _, Check, Location, {Defaults, _, _}} = Fun, Export = export(Kind, Tuple), case [Clause || {_, Clause} <- ets:lookup(CTable, Tuple)] of [] -> warn_bodyless_function(Line, File, Module, Kind, Tuple), unwrap_definition(T, File, Module, CTable, All, Private); Clauses -> Unwrapped = {Tuple, Kind, Line, Location, function_for_stored_definition(Line, Export, Clauses)}, NewPrivate = if Kind == defp; Kind == defmacrop -> [{Tuple, Kind, Line, Check, Defaults}|Private]; true -> Private end, unwrap_definition(T, File, Module, CTable, [Unwrapped|All], NewPrivate) end; unwrap_definition([], _File, _Module, _CTable, All, Private) -> {All, Private}. split_definition([{Tuple, def, Line, Location, Body}|T], Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, Functions) -> split_definition(T, Unreachable, [Tuple|Def], Defp, Defmacro, Defmacrop, [export(def, Tuple)|Exports], add_definition(Line, Location, Body, Functions)); split_definition([{Tuple, defp, Line, Location, Body}|T], Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, Functions) -> case lists:member(Tuple, Unreachable) of false -> split_definition(T, Unreachable, Def, [Tuple|Defp], Defmacro, Defmacrop, Exports, add_definition(Line, Location, Body, Functions)); true -> split_definition(T, Unreachable, Def, [Tuple|Defp], Defmacro, Defmacrop, Exports, Functions) end; split_definition([{Tuple, defmacro, Line, Location, Body}|T], Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, Functions) -> split_definition(T, Unreachable, Def, Defp, [Tuple|Defmacro], Defmacrop, [export(defmacro, Tuple)|Exports], add_definition(Line, Location, Body, Functions)); split_definition([{Tuple, defmacrop, _Line, _Location, _Body}|T], Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, Functions) -> split_definition(T, Unreachable, Def, Defp, Defmacro, [Tuple|Defmacrop], Exports, Functions); split_definition([], Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, {Head, Tail}) -> {Def, Defp, Defmacro, Defmacrop, Exports, Head ++ Tail, Unreachable}. %% Helpers export(Kind, {Name, Arity}) when Kind == defmacro; Kind == defmacrop -> {elixir_utils:macro_name(Name), Arity + 1}; export(Kind, {Name, Arity}) when Kind == def; Kind == defp -> {Name, Arity}. function_for_stored_definition(Line, {Name, Arity}, Clauses) -> {function, Line, Name, Arity, Clauses}. add_definition(_Line, nil, Body, {Head, Tail}) -> {[Body|Head], Tail}; add_definition(Line, Location, Body, {Head, Tail}) -> {Head, [{attribute, Line, file, Location}, Body|Tail]}. default_function_for(Kind, Name, {clause, Line, Args, _Guards, _Exprs} = Clause) when Kind == defmacro; Kind == defmacrop -> {function, Line, Name, length(Args) - 1, [Clause]}; default_function_for(_, Name, {clause, Line, Args, _Guards, _Exprs} = Clause) -> {function, Line, Name, length(Args), [Clause]}. warn_bodyless_function(_Line, _File, Special, _Kind, _Tuple) when Special == 'Elixir.Kernel.SpecialForms'; Special == 'Elixir.Module' -> ok; warn_bodyless_function(Line, File, _Module, Kind, Tuple) -> elixir_errors:form_warn([{line, Line}], File, ?MODULE, {bodyless_fun, Kind, Tuple}), ok. %% Store each definition in the table. %% This function also checks and emit warnings in case %% the kind, of the visibility of the function changes. store_each(Check, Kind, File, Location, Module, Defaults, {function, Line, Name, Arity, Clauses}) -> Data = elixir_module:data_table(Module), Defs = elixir_module:defs_table(Module), Clas = elixir_module:clas_table(Module), Tuple = {Name, Arity}, HasBody = Clauses =/= [], case ets:lookup(Defs, Tuple) of [{Tuple, StoredKind, StoredLine, StoredFile, StoredCheck, StoredLocation, {StoredDefaults, LastHasBody, LastDefaults}}] -> FinalLine = StoredLine, FinalLocation = StoredLocation, FinalDefaults = {max(Defaults, StoredDefaults), HasBody, Defaults}, check_valid_kind(Line, File, Name, Arity, Kind, StoredKind), (Check and StoredCheck) andalso check_valid_clause(Line, File, Name, Arity, Kind, Data, StoredLine, StoredFile), check_valid_defaults(Line, File, Name, Arity, Kind, Defaults, LastDefaults, LastHasBody); [] -> FinalLine = Line, FinalLocation = Location, FinalDefaults = {Defaults, HasBody, Defaults} end, Check andalso ets:insert(Data, {?last_def, {Name, Arity}}), ets:insert(Clas, [{Tuple, Clause} || Clause <- Clauses]), ets:insert(Defs, {Tuple, Kind, FinalLine, File, Check, FinalLocation, FinalDefaults}). %% Validations check_valid_kind(_Line, _File, _Name, _Arity, Kind, Kind) -> []; check_valid_kind(Line, File, Name, Arity, Kind, StoredKind) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {changed_kind, {Name, Arity, StoredKind, Kind}}). check_valid_clause(Line, File, Name, Arity, Kind, Data, StoredLine, StoredFile) -> case ets:lookup_element(Data, ?last_def, 2) of {Name, Arity} -> []; [] -> []; _ -> Relative = elixir_utils:relative_to_cwd(elixir_utils:relative_to_cwd(StoredFile)), elixir_errors:form_warn([{line, Line}], File, ?MODULE, {ungrouped_clause, {Kind, Name, Arity, StoredLine, Relative}}) end. % Any clause after clause with defaults (body less does not count) check_valid_defaults(Line, File, Name, Arity, Kind, _, StoredDefaults, true) when StoredDefaults > 0 -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {clauses_with_defaults, {Kind, Name, Arity}}); % Clause without defaults check_valid_defaults(_Line, _File, _Name, _Arity, _Kind, 0, _, _) -> []; % Clause with defaults after clause without defaults check_valid_defaults(Line, File, Name, Arity, Kind, _, 0, _) -> elixir_errors:form_warn([{line, Line}], File, ?MODULE, {out_of_order_defaults, {Kind, Name, Arity}}); % Clause with defaults after clause with defaults check_valid_defaults(Line, File, Name, Arity, Kind, _, _, _) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {clauses_with_defaults, {Kind, Name, Arity}}). check_previous_defaults(Line, Module, Name, Arity, Kind, Defaults, E) -> Matches = ets:match(elixir_module:defs_table(Module), {{Name, '$2'}, '$1', '_', '_', '_', '_', {'$3', '_', '_'}}), [ begin elixir_errors:form_error([{line, Line}], ?m(E, file), ?MODULE, {defs_with_defaults, Name, {Kind, Arity}, {K, A}}) end || [K, A, D] <- Matches, A /= Arity, D /= 0, defaults_conflict(A, D, Arity, Defaults)]. defaults_conflict(A, D, Arity, Defaults) -> ((Arity >= (A - D)) andalso (Arity < A)) orelse ((A >= (Arity - Defaults)) andalso (A < Arity)). check_args_for_bodyless_clause(Line, Args, E) -> [ begin elixir_errors:form_error([{line, Line}], ?m(E, file), ?MODULE, invalid_args_for_bodyless_clause) end || Arg <- Args, invalid_arg(Arg) ]. invalid_arg({Name, _, Kind}) when is_atom(Name), is_atom(Kind) -> false; invalid_arg({'\\\\', _, [{Name, _, Kind}, _]}) when is_atom(Name), is_atom(Kind) -> false; invalid_arg(_) -> true. assert_no_aliases_name(Line, '__aliases__', [Atom], #{file := File}) when is_atom(Atom) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {no_alias, Atom}); assert_no_aliases_name(_Line, _Aliases, _Args, _S) -> ok. assert_valid_name(Line, Kind, is_record, [_, _], #{file := File}) when Kind == defp; Kind == def -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {is_record, Kind}); assert_valid_name(_Line, _Kind, _Name, _Args, _S) -> ok. %% Format errors format_error({bodyless_fun, Kind, {Name, Arity}}) -> io_lib:format("bodyless clause provided for nonexistent ~ts ~ts/~B", [Kind, Name, Arity]); format_error({no_module, {Kind, Name, Arity}}) -> io_lib:format("cannot define function outside module, invalid scope for ~ts ~ts/~B", [Kind, Name, Arity]); format_error({defs_with_defaults, Name, {Kind, Arity}, {K, A}}) when Arity > A -> io_lib:format("~ts ~ts/~B defaults conflicts with ~ts ~ts/~B", [Kind, Name, Arity, K, Name, A]); format_error({defs_with_defaults, Name, {Kind, Arity}, {K, A}}) when Arity < A -> io_lib:format("~ts ~ts/~B conflicts with defaults from ~ts ~ts/~B", [Kind, Name, Arity, K, Name, A]); format_error({clauses_with_defaults, {Kind, Name, Arity}}) -> io_lib:format("~ts ~ts/~B has default values and multiple clauses, " "define a function head with the defaults", [Kind, Name, Arity]); format_error({out_of_order_defaults, {Kind, Name, Arity}}) -> io_lib:format("clause with defaults should be the first clause in ~ts ~ts/~B", [Kind, Name, Arity]); format_error({ungrouped_clause, {Kind, Name, Arity, OrigLine, OrigFile}}) -> io_lib:format("clauses for the same ~ts should be grouped together, ~ts ~ts/~B was previously defined (~ts:~B)", [Kind, Kind, Name, Arity, OrigFile, OrigLine]); format_error({changed_kind, {Name, Arity, Previous, Current}}) -> io_lib:format("~ts ~ts/~B already defined as ~ts", [Current, Name, Arity, Previous]); format_error({no_alias, Atom}) -> io_lib:format("function names should start with lowercase characters or underscore, invalid name ~ts", [Atom]); format_error({invalid_def, Kind, NameAndArgs}) -> io_lib:format("invalid syntax in ~ts ~ts", [Kind, 'Elixir.Macro':to_string(NameAndArgs)]); format_error(invalid_args_for_bodyless_clause) -> "can use only variables and \\\\ as arguments of bodyless clause"; format_error({is_record, Kind}) -> io_lib:format("cannot define function named ~ts is_record/2 due to compability " "issues with the Erlang compiler (it is a known bug)", [Kind]); format_error({missing_do, Kind}) -> io_lib:format("missing do keyword in ~ts", [Kind]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_def_defaults.erl000066400000000000000000000050001254730255300244460ustar00rootroot00000000000000% Handle default clauses for function definitions. -module(elixir_def_defaults). -export([expand/2, unpack/4]). -include("elixir.hrl"). expand(Args, E) -> NoContext = E#{context := nil}, lists:mapfoldl(fun ({'\\\\', Meta, [Left, Right]}, Acc) -> {ELeft, EL} = elixir_exp:expand(Left, Acc), {ERight, _} = elixir_exp:expand(Right, NoContext), {{'\\\\', Meta, [ELeft, ERight]}, EL}; (Left, Acc) -> elixir_exp:expand(Left, Acc) end, E, Args). unpack(Kind, Name, Args, S) -> unpack_each(Kind, Name, Args, [], [], S). %% Helpers %% Unpack default from given args. %% Returns the given arguments without their default %% clauses and a list of clauses for the default calls. unpack_each(Kind, Name, [{'\\\\', DefMeta, [Expr, _]}|T] = List, Acc, Clauses, S) -> Base = wrap_kind(Kind, build_match(Acc, [])), {Args, Invoke} = extract_defaults(List, length(Base), [], []), {DefArgs, SA} = elixir_clauses:match(fun elixir_translator:translate_args/2, Base ++ Args, S), {DefInvoke, _} = elixir_translator:translate_args(Base ++ Invoke, SA), Line = ?line(DefMeta), Call = {call, Line, {atom, Line, name_for_kind(Kind, Name)}, DefInvoke }, Clause = {clause, Line, DefArgs, [], [Call]}, unpack_each(Kind, Name, T, [Expr|Acc], [Clause|Clauses], S); unpack_each(Kind, Name, [H|T], Acc, Clauses, S) -> unpack_each(Kind, Name, T, [H|Acc], Clauses, S); unpack_each(_Kind, _Name, [], Acc, Clauses, _S) -> {lists:reverse(Acc), lists:reverse(Clauses)}. % Extract default values from args following the current default clause. extract_defaults([{'\\\\', _, [_Expr, Default]}|T], Counter, NewArgs, NewInvoke) -> extract_defaults(T, Counter, NewArgs, [Default|NewInvoke]); extract_defaults([_|T], Counter, NewArgs, NewInvoke) -> H = {elixir_utils:atom_concat(["x", Counter]), [], nil}, extract_defaults(T, Counter + 1, [H|NewArgs], [H|NewInvoke]); extract_defaults([], _Counter, NewArgs, NewInvoke) -> {lists:reverse(NewArgs), lists:reverse(NewInvoke)}. % Build matches for all the previous argument until the current default clause. build_match([], Acc) -> Acc; build_match([_|T], Acc) -> Var = {elixir_utils:atom_concat(["x", length(T)]), [], nil}, build_match(T, [Var|Acc]). % Given the invoked function name based on the kind wrap_kind(Kind, Args) when Kind == defmacro; Kind == defmacrop -> [{c, [], nil}|Args]; wrap_kind(_Kind, Args) -> Args. name_for_kind(Kind, Name) when Kind == defmacro; Kind == defmacrop -> elixir_utils:macro_name(Name); name_for_kind(_Kind, Name) -> Name.elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_def_overridable.erl000066400000000000000000000053621254730255300251500ustar00rootroot00000000000000% Holds the logic responsible for defining overridable functions and handling super. -module(elixir_def_overridable). -export([setup/1, overridable/1, overridable/2, name/2, super/2, store_pending/1, ensure_defined/4, format_error/1]). -include("elixir.hrl"). -define(attr, {elixir, overridable}). setup(Module) -> overridable(Module, []). overridable(Module) -> ets:lookup_element(elixir_module:data_table(Module), ?attr, 2). overridable(Module, Value) -> ets:insert(elixir_module:data_table(Module), {?attr, Value}). %% Check if an overridable function is defined. ensure_defined(Meta, Module, Tuple, S) -> Overridable = overridable(Module), case orddict:find(Tuple, Overridable) of {ok, {_, _, _, _}} -> ok; _ -> elixir_errors:form_error(Meta, S#elixir_scope.file, ?MODULE, {no_super, Module, Tuple}) end. %% Gets the name based on the function and stored overridables name(Module, Function) -> name(Module, Function, overridable(Module)). name(_Module, {Name, _} = Function, Overridable) -> {Count, _, _, _} = orddict:fetch(Function, Overridable), elixir_utils:atom_concat([Name, " (overridable ", Count, ")"]). %% Store store(Module, Function, GenerateName) -> Overridable = overridable(Module), case orddict:fetch(Function, Overridable) of {_Count, _Clause, _Neighbours, true} -> ok; {Count, Clause, Neighbours, false} -> overridable(Module, orddict:store(Function, {Count, Clause, Neighbours, true}, Overridable)), {{{Name, Arity}, Kind, Line, File, _Check, Location, {Defaults, _HasBody, _LastDefaults}}, Clauses} = Clause, {FinalKind, FinalName} = case GenerateName of true -> {defp, name(Module, Function, Overridable)}; false -> {Kind, Name} end, case elixir_compiler:get_opt(internal) of false -> 'Elixir.Module.LocalsTracker':reattach(Module, Kind, {Name, Arity}, Neighbours); true -> ok end, Def = {function, Line, FinalName, Arity, Clauses}, elixir_def:store_each(false, FinalKind, File, Location, Module, Defaults, Def) end. super(Module, Function) -> store(Module, Function, true). store_pending(Module) -> _ = [store(Module, X, false) || {X, {_, _, _, false}} <- overridable(Module), not 'Elixir.Module':'defines?'(Module, X)], ok. %% Error handling format_error({no_super, Module, {Name, Arity}}) -> Bins = [format_fa(X) || {X, {_, _, _, _}} <- overridable(Module)], Joined = 'Elixir.Enum':join(Bins, <<", ">>), io_lib:format("no super defined for ~ts/~B in module ~ts. Overridable functions available are: ~ts", [Name, Arity, elixir_aliases:inspect(Module), Joined]). format_fa({Name, Arity}) -> A = atom_to_binary(Name, utf8), B = integer_to_binary(Arity), <>. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_dispatch.erl000066400000000000000000000273421254730255300236350ustar00rootroot00000000000000%% Helpers related to dispatching to imports and references. %% This module access the information stored on the scope %% by elixir_import and therefore assumes it is normalized (ordsets) -module(elixir_dispatch). -export([dispatch_import/5, dispatch_require/6, require_function/5, import_function/4, expand_import/6, expand_require/5, default_functions/0, default_macros/0, default_requires/0, find_import/4, format_error/1]). -include("elixir.hrl"). -import(ordsets, [is_element/2]). -define(kernel, 'Elixir.Kernel'). default_functions() -> [{?kernel, elixir_imported_functions()}]. default_macros() -> [{?kernel, elixir_imported_macros()}]. default_requires() -> ['Elixir.Kernel', 'Elixir.Kernel.Typespec']. %% This is used by elixir_quote. Note we don't record the %% import locally because at that point there is no %% ambiguity. find_import(Meta, Name, Arity, E) -> Tuple = {Name, Arity}, case find_dispatch(Meta, Tuple, [], E) of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), %% elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), Receiver; {macro, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), %% elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), Receiver; _ -> false end. %% Function retrieval import_function(Meta, Name, Arity, E) -> Tuple = {Name, Arity}, case find_dispatch(Meta, Tuple, [], E) of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), remote_function(Meta, Receiver, Name, Arity, E); {macro, _Receiver} -> false; {import, Receiver} -> require_function(Meta, Receiver, Name, Arity, E); false -> case elixir_import:special_form(Name, Arity) of true -> false; false -> elixir_locals:record_local(Tuple, ?m(E, module), ?m(E, function)), {local, Name, Arity} end end. require_function(Meta, Receiver, Name, Arity, E) -> case is_element({Name, Arity}, get_optional_macros(Receiver)) of true -> false; false -> remote_function(Meta, Receiver, Name, Arity, E) end. remote_function(Meta, Receiver, Name, Arity, E) -> check_deprecation(Meta, Receiver, Name, Arity, E), elixir_lexical:record_remote(Receiver, ?m(E, lexical_tracker)), case elixir_rewrite:inline(Receiver, Name, Arity) of {AR, AN} -> {remote, AR, AN, Arity}; false -> {remote, Receiver, Name, Arity} end. %% Dispatches dispatch_import(Meta, Name, Args, E, Callback) -> Arity = length(Args), case expand_import(Meta, {Name, Arity}, Args, E, [], false) of {ok, Receiver, Quoted} -> expand_quoted(Meta, Receiver, Name, Arity, Quoted, E); {ok, Receiver, NewName, NewArgs} -> elixir_exp:expand({{'.', [], [Receiver, NewName]}, Meta, NewArgs}, E); error -> Callback() end. dispatch_require(Meta, Receiver, Name, Args, E, Callback) when is_atom(Receiver) -> Arity = length(Args), case elixir_rewrite:inline(Receiver, Name, Arity) of {AR, AN} -> Callback(AR, AN, Args); false -> case expand_require(Meta, Receiver, {Name, Arity}, Args, E) of {ok, Receiver, Quoted} -> expand_quoted(Meta, Receiver, Name, Arity, Quoted, E); error -> Callback(Receiver, Name, Args) end end; dispatch_require(_Meta, Receiver, Name, Args, _E, Callback) -> Callback(Receiver, Name, Args). %% Macros expansion expand_import(Meta, {Name, Arity} = Tuple, Args, E, Extra, External) -> Module = ?m(E, module), Dispatch = find_dispatch(Meta, Tuple, Extra, E), Function = ?m(E, function), AllowLocals = External orelse ((Function /= nil) andalso (Function /= Tuple)), Local = AllowLocals andalso elixir_locals:macro_for(Module, Name, Arity), case Dispatch of %% In case it is an import, we dispatch the import. {import, _} -> do_expand_import(Meta, Tuple, Args, Module, E, Dispatch); %% There is a local and an import. This is a conflict unless %% the receiver is the same as module (happens on bootstrap). {_, Receiver} when Local /= false, Receiver /= Module -> Error = {macro_conflict, {Receiver, Name, Arity}}, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, Error); %% There is no local. Dispatch the import. _ when Local == false -> do_expand_import(Meta, Tuple, Args, Module, E, Dispatch); %% Dispatch to the local. _ -> elixir_locals:record_local(Tuple, Module, Function), {ok, Module, expand_macro_fun(Meta, Local(), Module, Name, Args, E)} end. do_expand_import(Meta, {Name, Arity} = Tuple, Args, Module, E, Result) -> case Result of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), {ok, Receiver, Name, Args}; {macro, Receiver} -> check_deprecation(Meta, Receiver, Name, Arity, E), elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), {ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)}; {import, Receiver} -> case expand_require([{require, false}|Meta], Receiver, Tuple, Args, E) of {ok, _, _} = Response -> Response; error -> {ok, Receiver, Name, Args} end; false when Module == ?kernel -> case elixir_rewrite:inline(Module, Name, Arity) of {AR, AN} -> {ok, AR, AN, Args}; false -> error end; false -> error end. expand_require(Meta, Receiver, {Name, Arity} = Tuple, Args, E) -> check_deprecation(Meta, Receiver, Name, Arity, E), Module = ?m(E, module), case is_element(Tuple, get_optional_macros(Receiver)) of true -> Requires = ?m(E, requires), case (Receiver == Module) orelse is_element(Receiver, Requires) orelse skip_require(Meta) of true -> elixir_lexical:record_remote(Receiver, ?m(E, lexical_tracker)), {ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)}; false -> Info = {unrequired_module, {Receiver, Name, length(Args), Requires}}, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, Info) end; false -> error end. %% Expansion helpers expand_macro_fun(Meta, Fun, Receiver, Name, Args, E) -> Line = ?line(Meta), EArg = {Line, E}, try apply(Fun, [EArg|Args]) catch Kind:Reason -> Arity = length(Args), MFA = {Receiver, elixir_utils:macro_name(Name), Arity+1}, Info = [{Receiver, Name, Arity, [{file, "expanding macro"}]}, caller(Line, E)], erlang:raise(Kind, Reason, prune_stacktrace(erlang:get_stacktrace(), MFA, Info, EArg)) end. expand_macro_named(Meta, Receiver, Name, Arity, Args, E) -> ProperName = elixir_utils:macro_name(Name), ProperArity = Arity + 1, Fun = fun Receiver:ProperName/ProperArity, expand_macro_fun(Meta, Fun, Receiver, Name, Args, E). expand_quoted(Meta, Receiver, Name, Arity, Quoted, E) -> Line = ?line(Meta), Next = elixir_counter:next(), try elixir_exp:expand( elixir_quote:linify_with_context_counter(Line, {Receiver, Next}, Quoted), E) catch Kind:Reason -> MFA = {Receiver, elixir_utils:macro_name(Name), Arity+1}, Info = [{Receiver, Name, Arity, [{file, "expanding macro"}]}, caller(Line, E)], erlang:raise(Kind, Reason, prune_stacktrace(erlang:get_stacktrace(), MFA, Info, nil)) end. caller(Line, #{module := nil} = E) -> {elixir_compiler_0, '__FILE__', 1, location(Line, E)}; caller(Line, #{module := Module, function := nil} = E) -> {Module, '__MODULE__', 0, location(Line, E)}; caller(Line, #{module := Module, function := {Name, Arity}} = E) -> {Module, Name, Arity, location(Line, E)}. location(Line, E) -> [{file, elixir_utils:characters_to_list(elixir_utils:relative_to_cwd(?m(E, file)))}, {line, Line}]. %% Helpers skip_require(Meta) -> lists:keyfind(require, 1, Meta) == {require, false}. find_dispatch(Meta, Tuple, Extra, E) -> case is_import(Meta) of {import, _} = Import -> Import; false -> Funs = ?m(E, functions), Macs = Extra ++ ?m(E, macros), FunMatch = find_dispatch(Tuple, Funs), MacMatch = find_dispatch(Tuple, Macs), case {FunMatch, MacMatch} of {[], [Receiver]} -> {macro, Receiver}; {[Receiver], []} -> {function, Receiver}; {[], []} -> false; _ -> {Name, Arity} = Tuple, [First, Second|_] = FunMatch ++ MacMatch, Error = {ambiguous_call, {First, Second, Name, Arity}}, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, Error) end end. find_dispatch(Tuple, List) -> [Receiver || {Receiver, Set} <- List, is_element(Tuple, Set)]. is_import(Meta) -> case lists:keyfind(import, 1, Meta) of {import, _} = Import -> case lists:keyfind(context, 1, Meta) of {context, _} -> Import; false -> false end; false -> false end. % %% We've reached the macro wrapper fun, skip it with the rest prune_stacktrace([{_, _, [E|_], _}|_], _MFA, Info, E) -> Info; %% We've reached the invoked macro, skip it prune_stacktrace([{M, F, A, _}|_], {M, F, A}, Info, _E) -> Info; %% We've reached the elixir_dispatch internals, skip it with the rest prune_stacktrace([{Mod, _, _, _}|_], _MFA, Info, _E) when Mod == elixir_dispatch; Mod == elixir_exp -> Info; prune_stacktrace([H|T], MFA, Info, E) -> [H|prune_stacktrace(T, MFA, Info, E)]; prune_stacktrace([], _MFA, Info, _E) -> Info. %% ERROR HANDLING format_error({unrequired_module, {Receiver, Name, Arity, _Required}}) -> Module = elixir_aliases:inspect(Receiver), io_lib:format("you must require ~ts before invoking the macro ~ts.~ts/~B", [Module, Module, Name, Arity]); format_error({macro_conflict, {Receiver, Name, Arity}}) -> io_lib:format("call to local macro ~ts/~B conflicts with imported ~ts.~ts/~B, " "please rename the local macro or remove the conflicting import", [Name, Arity, elixir_aliases:inspect(Receiver), Name, Arity]); format_error({ambiguous_call, {Mod1, Mod2, Name, Arity}}) -> io_lib:format("function ~ts/~B imported from both ~ts and ~ts, call is ambiguous", [Name, Arity, elixir_aliases:inspect(Mod1), elixir_aliases:inspect(Mod2)]). %% INTROSPECTION %% Do not try to get macros from Erlang. Speeds up compilation a bit. get_optional_macros(erlang) -> []; get_optional_macros(Receiver) -> case code:ensure_loaded(Receiver) of {module, Receiver} -> try Receiver:'__info__'(macros) catch error:undef -> [] end; {error, _} -> [] end. elixir_imported_functions() -> try ?kernel:'__info__'(functions) catch error:undef -> [] end. elixir_imported_macros() -> try ?kernel:'__info__'(macros) catch error:undef -> [] end. check_deprecation(Meta, Receiver, Name, Arity, #{file := File}) -> case deprecation(Receiver, Name, Arity) of false -> ok; Message -> Warning = deprecation_message(Receiver, Name, Arity, Message), elixir_errors:warn(?line(Meta), File, Warning) end. deprecation_message(Receiver, '__using__', _Arity, Message) -> Warning = io_lib:format("use ~s is deprecated", [elixir_aliases:inspect(Receiver)]), deprecation_message(Warning, Message); deprecation_message(Receiver, Name, Arity, Message) -> Warning = io_lib:format("~s.~s/~B is deprecated", [elixir_aliases:inspect(Receiver), Name, Arity]), deprecation_message(Warning, Message). deprecation_message(Warning, Message) -> case Message of true -> Warning; Message -> Warning ++ ", " ++ Message end. deprecation(_, _, _) -> false. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_env.erl000066400000000000000000000046411254730255300226230ustar00rootroot00000000000000-module(elixir_env). -include("elixir.hrl"). -export([new/0, linify/1, env_to_scope/1, env_to_scope_with_vars/2]). -export([mergea/2, mergev/2, merge_vars/2, merge_opt_vars/2]). new() -> #{'__struct__' => 'Elixir.Macro.Env', module => nil, %% the current module file => <<"nofile">>, %% the current filename line => 1, %% the current line function => nil, %% the current function context => nil, %% can be match_vars, guards or nil requires => [], %% a set with modules required aliases => [], %% an orddict with aliases by new -> old names functions => [], %% a list with functions imported from module macros => [], %% a list with macros imported from module macro_aliases => [], %% keep aliases defined inside a macro context_modules => [], %% modules defined in the current context vars => [], %% a set of defined variables export_vars => nil, %% a set of variables to be exported in some constructs lexical_tracker => nil}. %% holds the lexical tracker pid linify({Line, Env}) -> Env#{line := Line}. env_to_scope(#{module := Module, file := File, function := Function, context := Context}) -> #elixir_scope{module=Module, file=File, function=Function, context=Context}. env_to_scope_with_vars(Env, Vars) -> (env_to_scope(Env))#elixir_scope{ vars=orddict:from_list(Vars), counter=[{'_', length(Vars)}] }. %% SCOPE MERGING %% Receives two scopes and return a new scope based on the second %% with their variables merged. mergev(E1, E2) when is_list(E1) -> E2#{ vars := merge_vars(E1, ?m(E2, vars)), export_vars := merge_opt_vars(E1, ?m(E2, export_vars)) }; mergev(E1, E2) -> E2#{ vars := merge_vars(?m(E1, vars), ?m(E2, vars)), export_vars := merge_opt_vars(?m(E1, export_vars), ?m(E2, export_vars)) }. %% Receives two scopes and return the later scope %% keeping the variables from the first (imports %% and everything else are passed forward). mergea(E1, E2) -> E2#{vars := ?m(E1, vars)}. merge_vars(V1, V2) -> ordsets:union(V1, V2). merge_opt_vars(_V1, nil) -> nil; merge_opt_vars(nil, _V2) -> nil; merge_opt_vars(V1, V2) -> ordsets:union(V1, V2). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_errors.erl000066400000000000000000000236131254730255300233470ustar00rootroot00000000000000% A bunch of helpers to help to deal with errors in Elixir source code. % This is not exposed in the Elixir language. -module(elixir_errors). -export([compile_error/3, compile_error/4, form_error/4, form_warn/4, parse_error/4, warn/2, warn/3, handle_file_warning/2, handle_file_warning/3, handle_file_error/2]). -include("elixir.hrl"). -spec warn(non_neg_integer(), binary(), unicode:chardata()) -> ok. warn(Line, File, Warning) when is_integer(Line), is_binary(File) -> warn(file_format(Line, File), Warning). -spec warn(unicode:chardata(), unicode:chardata()) -> ok. warn(Caller, Warning) -> do_warn([Caller, "warning: ", Warning, $\n]). %% General forms handling. -spec form_error(list(), binary(), module(), any()) -> no_return(). form_error(Meta, File, Module, Desc) -> compile_error(Meta, File, format_error(Module, Desc)). -spec form_warn(list(), binary(), module(), any()) -> ok. form_warn(Meta, File, Module, Desc) when is_list(Meta) -> {MetaFile, MetaLine} = meta_location(Meta, File), warn(MetaLine, MetaFile, format_error(Module, Desc)). %% Compilation error. -spec compile_error(list(), binary(), unicode:charlist()) -> no_return(). -spec compile_error(list(), binary(), string(), list()) -> no_return(). compile_error(Meta, File, Message) when is_list(Message) -> raise(Meta, File, 'Elixir.CompileError', elixir_utils:characters_to_binary(Message)). compile_error(Meta, File, Format, Args) when is_list(Format) -> compile_error(Meta, File, io_lib:format(Format, Args)). %% Tokenization parsing/errors. -spec parse_error(non_neg_integer(), binary() | {binary(), binary()}, binary(), binary()) -> no_return(). parse_error(Line, File, Error, <<>>) -> Message = case Error of <<"syntax error before: ">> -> <<"syntax error: expression is incomplete">>; _ -> Error end, do_raise(Line, File, 'Elixir.TokenMissingError', Message); %% Show a nicer message for missing end tokens parse_error(Line, File, <<"syntax error before: ">>, <<"'end'">>) -> do_raise(Line, File, 'Elixir.SyntaxError', <<"unexpected token: end">>); %% Produce a human-readable message for errors before a sigil parse_error(Line, File, <<"syntax error before: ">>, <<"{sigil,", _Rest/binary>> = Full) -> {sigil, _, Sigil, [Content|_], _} = parse_erl_term(Full), Content2 = case is_binary(Content) of true -> Content; false -> <<>> end, Message = <<"syntax error before: sigil ~", Sigil," starting with content '", Content2/binary, "'">>, do_raise(Line, File, 'Elixir.SyntaxError', Message); %% Aliases are wrapped in [''] parse_error(Line, File, Error, <<"['", _/binary>> = Full) when is_binary(Error) -> [AliasAtom] = parse_erl_term(Full), Alias = atom_to_binary(AliasAtom, utf8), do_raise(Line, File, 'Elixir.SyntaxError', <>); %% Binaries (and interpolation) are wrapped in [<<...>>] parse_error(Line, File, Error, <<"[", _/binary>> = Full) when is_binary(Error) -> Term = case parse_erl_term(Full) of [H|_] when is_binary(H) -> <<$", H/binary, $">>; _ -> <<$">> end, do_raise(Line, File, 'Elixir.SyntaxError', <>); %% Given a string prefix and suffix to insert the token inside the error message rather than append it parse_error(Line, File, {ErrorPrefix, ErrorSuffix}, Token) when is_binary(ErrorPrefix), is_binary(ErrorSuffix), is_binary(Token) -> Message = <>, do_raise(Line, File, 'Elixir.SyntaxError', Message); %% Everything else is fine as is parse_error(Line, File, Error, Token) when is_binary(Error), is_binary(Token) -> Message = <>, do_raise(Line, File, 'Elixir.SyntaxError', Message). %% Helper to parse terms which have been converted to binaries parse_erl_term(Term) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(Term)), {ok, Parsed} = erl_parse:parse_term(Tokens ++ [{dot, 1}]), Parsed. %% Handle warnings and errors from Erlang land (called during module compilation) %% Ignore on bootstrap handle_file_warning(true, _File, {_Line, sys_core_fold, nomatch_guard}) -> ok; handle_file_warning(true, _File, {_Line, sys_core_fold, {nomatch_shadow, _}}) -> ok; %% Ignore always handle_file_warning(_, _File, {_Line, sys_core_fold, useless_building}) -> ok; %% This is an Erlang bug, it considers {tuple, _}.call to always fail handle_file_warning(_, _File, {_Line, v3_kernel, bad_call}) -> ok; %% We handle unused local warnings ourselves handle_file_warning(_, _File, {_Line, erl_lint, {unused_function, _}}) -> ok; %% Make no_effect clauses pretty handle_file_warning(_, File, {Line, sys_core_fold, {no_effect, {erlang, F, A}}}) -> {Fmt, Args} = case erl_internal:comp_op(F, A) of true -> {"use of operator ~ts has no effect", [translate_comp_op(F)]}; false -> case erl_internal:bif(F, A) of false -> {"the call to :erlang.~ts/~B has no effect", [F, A]}; true -> {"the call to ~ts/~B has no effect", [F, A]} end end, Message = io_lib:format(Fmt, Args), warn(Line, File, Message); %% Rewrite undefined behaviour to check for protocols handle_file_warning(_, File, {Line, erl_lint, {undefined_behaviour_func, {Fun, Arity}, Module}}) -> {DefKind, Def, DefArity} = case atom_to_list(Fun) of "MACRO-" ++ Rest -> {macro, list_to_atom(Rest), Arity - 1}; _ -> {function, Fun, Arity} end, Kind = protocol_or_behaviour(Module), Raw = "undefined ~ts ~ts ~ts/~B (for ~ts ~ts)", Message = io_lib:format(Raw, [Kind, DefKind, Def, DefArity, Kind, elixir_aliases:inspect(Module)]), warn(Line, File, Message); handle_file_warning(_, File, {Line, erl_lint, {undefined_behaviour, Module}}) -> case elixir_compiler:get_opt(internal) of true -> ok; false -> Message = io_lib:format("behaviour ~ts undefined", [elixir_aliases:inspect(Module)]), warn(Line, File, Message) end; %% Ignore unused vars at "weird" lines (<= 0) handle_file_warning(_, _File, {Line, erl_lint, {unused_var, _Var}}) when Line =< 0 -> ok; %% Ignore shadowed and exported vars as we guarantee no conflicts ourselves handle_file_warning(_, _File, {_Line, erl_lint, {shadowed_var, _Var, _Where}}) -> ok; handle_file_warning(_, _File, {_Line, erl_lint, {exported_var, _Var, _Where}}) -> ok; %% Rewrite nomatch_guard to be more generic it can happen inside if, unless, etc handle_file_warning(_, File, {Line, sys_core_fold, nomatch_guard}) -> warn(Line, File, "this check/guard will always yield the same result"); %% Properly format other unused vars handle_file_warning(_, File, {Line, erl_lint, {unused_var, Var}}) -> Message = format_error(erl_lint, {unused_var, format_var(Var)}), warn(Line, File, Message); %% Handle literal eval failures handle_file_warning(_, File, {Line, sys_core_fold, {eval_failure, Error}}) -> #{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error), warn(Line, File, ["this expression will fail with ", elixir_aliases:inspect(Struct)]); %% Default behaviour handle_file_warning(_, File, {Line, Module, Desc}) -> Message = format_error(Module, Desc), warn(Line, File, Message). handle_file_warning(File, Desc) -> handle_file_warning(false, File, Desc). -spec handle_file_error(file:filename_all(), {non_neg_integer(), module(), any()}) -> no_return(). handle_file_error(File, {Line, erl_lint, {unsafe_var, Var, {In, _Where}}}) -> Translated = case In of 'orelse' -> 'or'; 'andalso' -> 'and'; _ -> In end, Message = io_lib:format("cannot define variable ~ts inside ~ts", [format_var(Var), Translated]), do_raise(Line, File, 'Elixir.CompileError', elixir_utils:characters_to_binary(Message)); handle_file_error(File, {Line, erl_lint, {spec_fun_undefined, {M, F, A}}}) -> Message = io_lib:format("spec for undefined function ~ts.~ts/~B", [elixir_aliases:inspect(M), F, A]), do_raise(Line, File, 'Elixir.CompileError', elixir_utils:characters_to_binary(Message)); handle_file_error(File, {Line, Module, Desc}) -> Message = format_error(Module, Desc), do_raise(Line, File, 'Elixir.CompileError', elixir_utils:characters_to_binary(Message)). %% Helpers raise(Meta, File, Kind, Message) when is_list(Meta) -> {MetaFile, MetaLine} = meta_location(Meta, File), do_raise(MetaLine, MetaFile, Kind, Message). file_format(0, File) -> io_lib:format("~ts: ", [elixir_utils:relative_to_cwd(File)]); file_format(Line, File) -> io_lib:format("~ts:~w: ", [elixir_utils:relative_to_cwd(File), Line]). format_var(Var) -> list_to_atom(lists:takewhile(fun(X) -> X /= $@ end, atom_to_list(Var))). format_error([], Desc) -> io_lib:format("~p", [Desc]); format_error(Module, Desc) -> Module:format_error(Desc). protocol_or_behaviour(Module) -> case is_protocol(Module) of true -> protocol; false -> behaviour end. is_protocol(Module) -> case code:ensure_loaded(Module) of {module, _} -> erlang:function_exported(Module, '__protocol__', 1) andalso Module:'__protocol__'(module) == Module; {error, _} -> false end. translate_comp_op('/=') -> '!='; translate_comp_op('=<') -> '<='; translate_comp_op('=:=') -> '==='; translate_comp_op('=/=') -> '!=='; translate_comp_op(Other) -> Other. meta_location(Meta, File) -> case elixir_utils:meta_location(Meta) of {F, L} -> {F, L}; nil -> {File, ?line(Meta)} end. do_warn(Warning) -> CompilerPid = get(elixir_compiler_pid), if CompilerPid =/= undefined -> elixir_code_server:cast({register_warning, CompilerPid}); true -> false end, io:put_chars(standard_error, Warning), ok. do_raise(none, File, Kind, Message) -> do_raise(0, File, Kind, Message); do_raise({Line, _, _}, File, Kind, Message) when is_integer(Line) -> do_raise(Line, File, Kind, Message); do_raise(Line, File, Kind, Message) when is_integer(Line), is_binary(File), is_binary(Message) -> try throw(ok) catch ok -> ok end, Stacktrace = erlang:get_stacktrace(), Exception = Kind:exception([{description, Message}, {file, File}, {line, Line}]), erlang:raise(error, Exception, tl(Stacktrace)). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_exp.erl000066400000000000000000000453001254730255300226240ustar00rootroot00000000000000-module(elixir_exp). -export([expand/2, expand_args/2, expand_arg/2]). -import(elixir_errors, [compile_error/3, compile_error/4]). -include("elixir.hrl"). %% = expand({'=', Meta, [Left, Right]}, E) -> assert_no_guard_scope(Meta, '=', E), {ERight, ER} = expand(Right, E), {ELeft, EL} = elixir_exp_clauses:match(fun expand/2, Left, E), {{'=', Meta, [ELeft, ERight]}, elixir_env:mergev(EL, ER)}; %% Literal operators expand({'{}', Meta, Args}, E) -> {EArgs, EA} = expand_args(Args, E), {{'{}', Meta, EArgs}, EA}; expand({'%{}', Meta, Args}, E) -> elixir_map:expand_map(Meta, Args, E); expand({'%', Meta, [Left, Right]}, E) -> elixir_map:expand_struct(Meta, Left, Right, E); expand({'<<>>', Meta, Args}, E) -> elixir_bitstring:expand(Meta, Args, E); %% Other operators expand({'__op__', Meta, [_, _] = Args}, E) -> {EArgs, EA} = expand_args(Args, E), {{'__op__', Meta, EArgs}, EA}; expand({'__op__', Meta, [_, _, _] = Args}, E) -> {EArgs, EA} = expand_args(Args, E), {{'__op__', Meta, EArgs}, EA}; expand({'->', Meta, _Args}, E) -> compile_error(Meta, ?m(E, file), "unhandled operator ->"); %% __block__ expand({'__block__', _Meta, []}, E) -> {nil, E}; expand({'__block__', _Meta, [Arg]}, E) -> expand(Arg, E); expand({'__block__', Meta, Args}, E) when is_list(Args) -> {EArgs, EA} = expand_many(Args, E), {{'__block__', Meta, EArgs}, EA}; %% __aliases__ expand({'__aliases__', Meta, _} = Alias, E) -> case elixir_aliases:expand(Alias, ?m(E, aliases), ?m(E, macro_aliases), ?m(E, lexical_tracker)) of Receiver when is_atom(Receiver) -> elixir_lexical:record_remote(Receiver, ?m(E, lexical_tracker)), {Receiver, E}; Aliases -> {EAliases, EA} = expand_args(Aliases, E), case lists:all(fun is_atom/1, EAliases) of true -> Receiver = elixir_aliases:concat(EAliases), elixir_lexical:record_remote(Receiver, ?m(E, lexical_tracker)), {Receiver, EA}; false -> compile_error(Meta, ?m(E, file), "an alias must expand to an atom " "at compilation time, but did not in \"~ts\". Use Module.concat/2 " "if you want to dynamically generate aliases", ['Elixir.Macro':to_string(Alias)]) end end; %% alias expand({alias, Meta, [Ref]}, E) -> expand({alias, Meta, [Ref, []]}, E); expand({alias, Meta, [Ref, KV]}, E) -> assert_no_match_or_guard_scope(Meta, alias, E), {ERef, ER} = expand(Ref, E), {EKV, ET} = expand_opts(Meta, alias, [as, warn], no_alias_opts(KV), ER), if is_atom(ERef) -> {{alias, Meta, [ERef, EKV]}, expand_alias(Meta, true, ERef, EKV, ET)}; true -> compile_error(Meta, ?m(E, file), "invalid argument for alias, expected a compile time atom or alias, got: ~ts", ['Elixir.Macro':to_string(Ref)]) end; expand({require, Meta, [Ref]}, E) -> expand({require, Meta, [Ref, []]}, E); expand({require, Meta, [Ref, KV]}, E) -> assert_no_match_or_guard_scope(Meta, require, E), {ERef, ER} = expand(Ref, E), {EKV, ET} = expand_opts(Meta, require, [as, warn], no_alias_opts(KV), ER), if is_atom(ERef) -> elixir_aliases:ensure_loaded(Meta, ERef, ET), {{require, Meta, [ERef, EKV]}, expand_require(Meta, ERef, EKV, ET)}; true -> compile_error(Meta, ?m(E, file), "invalid argument for require, expected a compile time atom or alias, got: ~ts", ['Elixir.Macro':to_string(Ref)]) end; expand({import, Meta, [Left]}, E) -> expand({import, Meta, [Left, []]}, E); expand({import, Meta, [Ref, KV]}, E) -> assert_no_match_or_guard_scope(Meta, import, E), {ERef, ER} = expand(Ref, E), {EKV, ET} = expand_opts(Meta, import, [only, except, warn], KV, ER), if is_atom(ERef) -> elixir_aliases:ensure_loaded(Meta, ERef, ET), {Functions, Macros} = elixir_import:import(Meta, ERef, EKV, ET), {{import, Meta, [ERef, EKV]}, expand_require(Meta, ERef, EKV, ET#{functions := Functions, macros := Macros})}; true -> compile_error(Meta, ?m(E, file), "invalid argument for import, expected a compile time atom or alias, got: ~ts", ['Elixir.Macro':to_string(Ref)]) end; %% Pseudo vars expand({'__MODULE__', _, Atom}, E) when is_atom(Atom) -> {?m(E, module), E}; expand({'__DIR__', _, Atom}, E) when is_atom(Atom) -> {filename:dirname(?m(E, file)), E}; expand({'__CALLER__', _, Atom} = Caller, E) when is_atom(Atom) -> {Caller, E}; expand({'__ENV__', Meta, Atom}, E) when is_atom(Atom) -> Env = elixir_env:linify({?line(Meta), E}), {{'%{}', [], maps:to_list(Env)}, E}; expand({{'.', DotMeta, [{'__ENV__', Meta, Atom}, Field]}, CallMeta, []}, E) when is_atom(Atom), is_atom(Field) -> Env = elixir_env:linify({?line(Meta), E}), case maps:is_key(Field, Env) of true -> {maps:get(Field, Env), E}; false -> {{{'.', DotMeta, [{'%{}', [], maps:to_list(Env)}, Field]}, CallMeta, []}, E} end; %% Quote expand({Unquote, Meta, [_]}, E) when Unquote == unquote; Unquote == unquote_splicing -> compile_error(Meta, ?m(E, file), "~p called outside quote", [Unquote]); expand({quote, Meta, [Opts]}, E) when is_list(Opts) -> case lists:keyfind(do, 1, Opts) of {do, Do} -> expand({quote, Meta, [lists:keydelete(do, 1, Opts), [{do, Do}]]}, E); false -> compile_error(Meta, ?m(E, file), "missing do keyword in quote") end; expand({quote, Meta, [_]}, E) -> compile_error(Meta, ?m(E, file), "invalid arguments for quote"); expand({quote, Meta, [KV, Do]}, E) when is_list(Do) -> Exprs = case lists:keyfind(do, 1, Do) of {do, Expr} -> Expr; false -> compile_error(Meta, E#elixir_scope.file, "missing do keyword in quote") end, ValidOpts = [context, location, line, file, unquote, bind_quoted], {EKV, ET} = expand_opts(Meta, quote, ValidOpts, KV, E), Context = case lists:keyfind(context, 1, EKV) of {context, Ctx} when is_atom(Ctx) and (Ctx /= nil) -> Ctx; {context, Ctx} -> compile_error(Meta, ?m(E, file), "invalid :context for quote, " "expected non nil compile time atom or alias, got: ~ts", ['Elixir.Kernel':inspect(Ctx)]); false -> case ?m(E, module) of nil -> 'Elixir'; Mod -> Mod end end, {File, Line} = case lists:keyfind(location, 1, EKV) of {location, keep} -> {elixir_utils:relative_to_cwd(?m(E, file)), false}; false -> { case lists:keyfind(file, 1, EKV) of {file, F} -> F; false -> nil end, case lists:keyfind(line, 1, EKV) of {line, L} -> L; false -> false end } end, {Binding, DefaultUnquote} = case lists:keyfind(bind_quoted, 1, EKV) of {bind_quoted, BQ} -> {BQ, false}; false -> {nil, true} end, Unquote = case lists:keyfind(unquote, 1, EKV) of {unquote, U} when is_boolean(U) -> U; false -> DefaultUnquote end, Q = #elixir_quote{line=Line, file=File, unquote=Unquote, context=Context}, {Quoted, _Q} = elixir_quote:quote(Exprs, Binding, Q, ET), expand(Quoted, ET); expand({quote, Meta, [_, _]}, E) -> compile_error(Meta, ?m(E, file), "invalid arguments for quote"); %% Functions expand({'&', _, [Arg]} = Original, E) when is_integer(Arg) -> {Original, E}; expand({'&', Meta, [Arg]}, E) -> assert_no_match_or_guard_scope(Meta, '&', E), case elixir_fn:capture(Meta, Arg, E) of {local, Fun, Arity} -> {{'&', Meta, [{'/', [], [{Fun, [], nil}, Arity]}]}, E}; {expanded, Expr, EE} -> expand(Expr, EE) end; expand({fn, Meta, Pairs}, E) -> assert_no_match_or_guard_scope(Meta, fn, E), elixir_fn:expand(Meta, Pairs, E); %% Case/Receive/Try expand({'cond', Meta, [KV]}, E) -> assert_no_match_or_guard_scope(Meta, 'cond', E), {EClauses, EC} = elixir_exp_clauses:'cond'(Meta, KV, E), {{'cond', Meta, [EClauses]}, EC}; expand({'case', Meta, [Expr, KV]}, E) -> assert_no_match_or_guard_scope(Meta, 'case', E), {EExpr, EE} = expand(Expr, E), {EClauses, EC} = elixir_exp_clauses:'case'(Meta, KV, EE), FClauses = case (lists:keyfind(optimize_boolean, 1, Meta) == {optimize_boolean, true}) and elixir_utils:returns_boolean(EExpr) of true -> rewrite_case_clauses(EClauses); false -> EClauses end, {{'case', Meta, [EExpr, FClauses]}, EC}; expand({'receive', Meta, [KV]}, E) -> assert_no_match_or_guard_scope(Meta, 'receive', E), {EClauses, EC} = elixir_exp_clauses:'receive'(Meta, KV, E), {{'receive', Meta, [EClauses]}, EC}; expand({'try', Meta, [KV]}, E) -> assert_no_match_or_guard_scope(Meta, 'try', E), {EClauses, EC} = elixir_exp_clauses:'try'(Meta, KV, E), {{'try', Meta, [EClauses]}, EC}; %% Comprehensions expand({for, Meta, [_|_] = Args}, E) -> elixir_for:expand(Meta, Args, E); %% Super expand({super, Meta, Args}, E) when is_list(Args) -> assert_no_match_or_guard_scope(Meta, super, E), {EArgs, EA} = expand_args(Args, E), {{super, Meta, EArgs}, EA}; %% Vars expand({'^', Meta, [Arg]}, #{context := match} = E) -> case expand(Arg, E) of {{Name, _, Kind} = EArg, EA} when is_atom(Name), is_atom(Kind) -> {{'^', Meta, [EArg]}, EA}; _ -> Msg = "invalid argument for unary operator ^, expected an existing variable, got: ^~ts", compile_error(Meta, ?m(E, file), Msg, ['Elixir.Macro':to_string(Arg)]) end; expand({'^', Meta, [Arg]}, E) -> compile_error(Meta, ?m(E, file), "cannot use ^~ts outside of match clauses", ['Elixir.Macro':to_string(Arg)]); expand({'_', _, Kind} = Var, E) when is_atom(Kind) -> {Var, E}; expand({Name, Meta, Kind} = Var, #{context := match, export_vars := Export} = E) when is_atom(Name), is_atom(Kind) -> Pair = {Name, var_kind(Meta, Kind)}, NewVars = ordsets:add_element(Pair, ?m(E, vars)), NewExport = case (Export /= nil) of true -> ordsets:add_element(Pair, Export); false -> Export end, {Var, E#{vars := NewVars, export_vars := NewExport}}; expand({Name, Meta, Kind} = Var, #{vars := Vars} = E) when is_atom(Name), is_atom(Kind) -> case lists:member({Name, var_kind(Meta, Kind)}, Vars) of true -> {Var, E}; false -> VarMeta = lists:keyfind(var, 1, Meta), if VarMeta == {var, true} -> compile_error(Meta, ?m(E, file), "expected var \"~ts\"~ts to expand to an existing variable " "or be part of a match", [Name, elixir_scope:context_info(Kind)]); true -> expand({Name, Meta, []}, E) end end; %% Local calls expand({Atom, Meta, Args}, E) when is_atom(Atom), is_list(Meta), is_list(Args) -> assert_no_ambiguous_op(Atom, Meta, Args, E), elixir_dispatch:dispatch_import(Meta, Atom, Args, E, fun() -> expand_local(Meta, Atom, Args, E) end); %% Remote calls expand({{'.', DotMeta, [Left, Right]}, Meta, Args}, E) when (is_tuple(Left) orelse is_atom(Left)), is_atom(Right), is_list(Meta), is_list(Args) -> {ELeft, EL} = expand(Left, E), elixir_dispatch:dispatch_require(Meta, ELeft, Right, Args, EL, fun(AR, AF, AA) -> expand_remote(AR, DotMeta, AF, Meta, AA, E, EL) end); %% Anonymous calls expand({{'.', DotMeta, [Expr]}, Meta, Args}, E) when is_list(Args) -> {EExpr, EE} = expand(Expr, E), if is_atom(EExpr) -> compile_error(Meta, ?m(E, file), "invalid function call :~ts.()", [EExpr]); true -> {EArgs, EA} = expand_args(Args, elixir_env:mergea(E, EE)), {{{'.', DotMeta, [EExpr]}, Meta, EArgs}, elixir_env:mergev(EE, EA)} end; %% Invalid calls expand({_, Meta, Args} = Invalid, E) when is_list(Meta) and is_list(Args) -> compile_error(Meta, ?m(E, file), "invalid call ~ts", ['Elixir.Macro':to_string(Invalid)]); expand({_, _, _} = Tuple, E) -> compile_error([{line, 0}], ?m(E, file), "invalid quoted expression: ~ts", ['Elixir.Kernel':inspect(Tuple, [])]); %% Literals expand({Left, Right}, E) -> {[ELeft, ERight], EE} = expand_args([Left, Right], E), {{ELeft, ERight}, EE}; expand(List, #{context := match} = E) when is_list(List) -> expand_list(List, fun expand/2, E, []); expand(List, E) when is_list(List) -> {EArgs, {EC, EV}} = expand_list(List, fun expand_arg/2, {E, E}, []), {EArgs, elixir_env:mergea(EV, EC)}; expand(Function, E) when is_function(Function) -> case (erlang:fun_info(Function, type) == {type, external}) andalso (erlang:fun_info(Function, env) == {env, []}) of true -> {Function, E}; false -> compile_error([{line, 0}], ?m(E, file), "invalid quoted expression: ~ts", ['Elixir.Kernel':inspect(Function)]) end; expand(Other, E) when is_number(Other); is_atom(Other); is_binary(Other); is_pid(Other) -> {Other, E}; expand(Other, E) -> compile_error([{line, 0}], ?m(E, file), "invalid quoted expression: ~ts", ['Elixir.Kernel':inspect(Other)]). %% Helpers expand_list([{'|', Meta, [_, _] = Args}], Fun, Acc, List) -> {EArgs, EAcc} = lists:mapfoldl(Fun, Acc, Args), expand_list([], Fun, EAcc, [{'|', Meta, EArgs}|List]); expand_list([H|T], Fun, Acc, List) -> {EArg, EAcc} = Fun(H, Acc), expand_list(T, Fun, EAcc, [EArg|List]); expand_list([], _Fun, Acc, List) -> {lists:reverse(List), Acc}. expand_many(Args, E) -> lists:mapfoldl(fun expand/2, E, Args). %% Variables in arguments are not propagated from one %% argument to the other. For instance: %% %% x = 1 %% foo(x = x + 2, x) %% x %% %% Should be the same as: %% %% foo(3, 1) %% 3 %% %% However, lexical information is. expand_arg(Arg, Acc) when is_number(Arg); is_atom(Arg); is_binary(Arg); is_pid(Arg) -> {Arg, Acc}; expand_arg(Arg, {Acc1, Acc2}) -> {EArg, EAcc} = expand(Arg, Acc1), {EArg, {elixir_env:mergea(Acc1, EAcc), elixir_env:mergev(Acc2, EAcc)}}. expand_args([Arg], E) -> {EArg, EE} = expand(Arg, E), {[EArg], EE}; expand_args(Args, #{context := match} = E) -> expand_many(Args, E); expand_args(Args, E) -> {EArgs, {EC, EV}} = lists:mapfoldl(fun expand_arg/2, {E, E}, Args), {EArgs, elixir_env:mergea(EV, EC)}. %% Match/var helpers var_kind(Meta, Kind) -> case lists:keyfind(counter, 1, Meta) of {counter, Counter} -> Counter; false -> Kind end. %% Locals assert_no_ambiguous_op(Name, Meta, [Arg], E) -> case lists:keyfind(ambiguous_op, 1, Meta) of {ambiguous_op, Kind} -> case lists:member({Name, Kind}, ?m(E, vars)) of true -> compile_error(Meta, ?m(E, file), "\"~ts ~ts\" looks like a function call but " "there is a variable named \"~ts\", please use explicit parentheses or even spaces", [Name, 'Elixir.Macro':to_string(Arg), Name]); false -> ok end; _ -> ok end; assert_no_ambiguous_op(_Atom, _Meta, _Args, _E) -> ok. expand_local(Meta, Name, Args, #{function := nil} = E) -> compile_error(Meta, ?m(E, file), "undefined function ~ts/~B", [Name, length(Args)]); expand_local(Meta, Name, Args, #{module := Module, function := Function} = E) -> elixir_locals:record_local({Name, length(Args)}, Module, Function), {EArgs, EA} = expand_args(Args, E), {{Name, Meta, EArgs}, EA}. %% Remote expand_remote(Receiver, DotMeta, Right, Meta, Args, E, EL) -> if is_atom(Receiver) -> elixir_lexical:record_remote(Receiver, ?m(E, lexical_tracker)); true -> ok end, {EArgs, EA} = expand_args(Args, E), {elixir_rewrite:rewrite(Receiver, DotMeta, Right, Meta, EArgs), elixir_env:mergev(EL, EA)}. %% Lexical helpers expand_opts(Meta, Kind, Allowed, Opts, E) -> {EOpts, EE} = expand(Opts, E), validate_opts(Meta, Kind, Allowed, EOpts, EE), {EOpts, EE}. validate_opts(Meta, Kind, Allowed, Opts, E) when is_list(Opts) -> [begin compile_error(Meta, ?m(E, file), "unsupported option ~ts given to ~s", ['Elixir.Macro':to_string(Key), Kind]) end || {Key, _} <- Opts, not lists:member(Key, Allowed)]; validate_opts(Meta, Kind, _Allowed, _Opts, E) -> compile_error(Meta, ?m(E, file), "invalid options for ~s, expected a keyword list", [Kind]). no_alias_opts(KV) when is_list(KV) -> case lists:keyfind(as, 1, KV) of {as, As} -> lists:keystore(as, 1, KV, {as, no_alias_expansion(As)}); false -> KV end; no_alias_opts(KV) -> KV. no_alias_expansion({'__aliases__', Meta, [H|T]}) when (H /= 'Elixir') and is_atom(H) -> {'__aliases__', Meta, ['Elixir', H|T]}; no_alias_expansion(Other) -> Other. expand_require(Meta, Ref, KV, E) -> RE = E#{requires := ordsets:add_element(Ref, ?m(E, requires))}, expand_alias(Meta, false, Ref, KV, RE). expand_alias(Meta, IncludeByDefault, Ref, KV, #{context_modules := Context} = E) -> New = expand_as(lists:keyfind(as, 1, KV), Meta, IncludeByDefault, Ref, E), %% Add the alias to context_modules if defined is true. %% This is used by defmodule in order to store the defined %% module in context modules. NewContext = case lists:keyfind(defined, 1, Meta) of {defined, Mod} when is_atom(Mod) -> [Mod|Context]; false -> Context end, {Aliases, MacroAliases} = elixir_aliases:store(Meta, New, Ref, KV, ?m(E, aliases), ?m(E, macro_aliases), ?m(E, lexical_tracker)), E#{aliases := Aliases, macro_aliases := MacroAliases, context_modules := NewContext}. expand_as({as, true}, _Meta, _IncludeByDefault, Ref, _E) -> elixir_aliases:last(Ref); expand_as({as, false}, _Meta, _IncludeByDefault, Ref, _E) -> Ref; expand_as({as, Atom}, Meta, _IncludeByDefault, _Ref, E) when is_atom(Atom) -> case length(string:tokens(atom_to_list(Atom), ".")) of 1 -> compile_error(Meta, ?m(E, file), "invalid value for keyword :as, expected an alias, got: ~ts", [elixir_aliases:inspect(Atom)]); 2 -> Atom; _ -> compile_error(Meta, ?m(E, file), "invalid value for keyword :as, expected a simple alias, got nested alias: ~ts", [elixir_aliases:inspect(Atom)]) end; expand_as(false, _Meta, IncludeByDefault, Ref, _E) -> if IncludeByDefault -> elixir_aliases:last(Ref); true -> Ref end; expand_as({as, Other}, Meta, _IncludeByDefault, _Ref, E) -> compile_error(Meta, ?m(E, file), "invalid value for keyword :as, expected an alias, got: ~ts", ['Elixir.Macro':to_string(Other)]). %% Assertions rewrite_case_clauses([{do, [ {'->', FalseMeta, [ [{'when', _, [Var, {'__op__', _, [ 'orelse', {{'.', _, [erlang, '=:=']}, _, [Var, nil]}, {{'.', _, [erlang, '=:=']}, _, [Var, false]} ]}]}], FalseExpr ]}, {'->', TrueMeta, [ [{'_', _, _}], TrueExpr ]} ]}]) -> [{do, [ {'->', FalseMeta, [[false], FalseExpr]}, {'->', TrueMeta, [[true], TrueExpr]} ]}]; rewrite_case_clauses(Clauses) -> Clauses. assert_no_match_or_guard_scope(Meta, Kind, E) -> assert_no_match_scope(Meta, Kind, E), assert_no_guard_scope(Meta, Kind, E). assert_no_match_scope(Meta, _Kind, #{context := match, file := File}) -> compile_error(Meta, File, "invalid expression in match"); assert_no_match_scope(_Meta, _Kind, _E) -> []. assert_no_guard_scope(Meta, _Kind, #{context := guard, file := File}) -> compile_error(Meta, File, "invalid expression in guard"); assert_no_guard_scope(_Meta, _Kind, _E) -> []. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_exp_clauses.erl000066400000000000000000000202361254730255300243440ustar00rootroot00000000000000%% Handle code related to args, guard and -> matching for case, %% fn, receive and friends. try is handled in elixir_try. -module(elixir_exp_clauses). -export([match/3, clause/5, def/5, head/2, 'case'/3, 'receive'/3, 'try'/3, 'cond'/3]). -import(elixir_errors, [compile_error/3, compile_error/4]). -include("elixir.hrl"). match(Fun, Expr, #{context := Context} = E) -> {EExpr, EE} = Fun(Expr, E#{context := match}), {EExpr, EE#{context := Context}}. def(Fun, Args, Guards, Body, E) -> {EArgs, EA} = match(Fun, Args, E), {EGuards, EG} = guard(Guards, EA#{context := guard}), {EBody, EB} = elixir_exp:expand(Body, EG#{context := ?m(E, context)}), {EArgs, EGuards, EBody, EB}. clause(Meta, Kind, Fun, {'->', ClauseMeta, [_, _]} = Clause, E) when is_function(Fun, 3) -> clause(Meta, Kind, fun(X, Acc) -> Fun(ClauseMeta, X, Acc) end, Clause, E); clause(_Meta, _Kind, Fun, {'->', Meta, [Left, Right]}, E) -> {ELeft, EL} = Fun(Left, E), {ERight, ER} = elixir_exp:expand(Right, EL), {{'->', Meta, [ELeft, ERight]}, ER}; clause(Meta, Kind, _Fun, _, E) -> compile_error(Meta, ?m(E, file), "expected -> clauses in ~ts", [Kind]). head([{'when', Meta, [_, _|_] = All}], E) -> {Args, Guard} = elixir_utils:split_last(All), {EArgs, EA} = match(fun elixir_exp:expand_args/2, Args, E), {EGuard, EG} = guard(Guard, EA#{context := guard}), {[{'when', Meta, EArgs ++ [EGuard]}], EG#{context := ?m(E, context)}}; head(Args, E) -> match(fun elixir_exp:expand_args/2, Args, E). guard({'when', Meta, [Left, Right]}, E) -> {ELeft, EL} = guard(Left, E), {ERight, ER} = guard(Right, EL), {{'when', Meta, [ELeft, ERight]}, ER}; guard(Other, E) -> elixir_exp:expand(Other, E). %% Case 'case'(Meta, [], E) -> compile_error(Meta, ?m(E, file), "missing do keyword in case"); 'case'(Meta, KV, E) when not is_list(KV) -> compile_error(Meta, ?m(E, file), "invalid arguments for case"); 'case'(Meta, KV, E) -> EE = E#{export_vars := []}, {EClauses, EVars} = lists:mapfoldl(fun(X, Acc) -> do_case(Meta, X, Acc, EE) end, [], KV), {EClauses, elixir_env:mergev(EVars, E)}. do_case(Meta, {'do', _} = Do, Acc, E) -> Fun = expand_one(Meta, 'case', 'do', fun head/2), expand_with_export(Meta, 'case', Fun, Do, Acc, E); do_case(Meta, {Key, _}, _Acc, E) -> compile_error(Meta, ?m(E, file), "unexpected keyword ~ts in case", [Key]). %% Cond 'cond'(Meta, [], E) -> compile_error(Meta, ?m(E, file), "missing do keyword in cond"); 'cond'(Meta, KV, E) when not is_list(KV) -> compile_error(Meta, ?m(E, file), "invalid arguments for cond"); 'cond'(Meta, KV, E) -> EE = E#{export_vars := []}, {EClauses, EVars} = lists:mapfoldl(fun(X, Acc) -> do_cond(Meta, X, Acc, EE) end, [], KV), {EClauses, elixir_env:mergev(EVars, E)}. do_cond(Meta, {'do', _} = Do, Acc, E) -> Fun = expand_one(Meta, 'cond', 'do', fun elixir_exp:expand_args/2), expand_with_export(Meta, 'cond', Fun, Do, Acc, E); do_cond(Meta, {Key, _}, _Acc, E) -> compile_error(Meta, ?m(E, file), "unexpected keyword ~ts in cond", [Key]). %% Receive 'receive'(Meta, [], E) -> compile_error(Meta, ?m(E, file), "missing do or after keyword in receive"); 'receive'(Meta, KV, E) when not is_list(KV) -> compile_error(Meta, ?m(E, file), "invalid arguments for receive"); 'receive'(Meta, KV, E) -> EE = E#{export_vars := []}, {EClauses, EVars} = lists:mapfoldl(fun(X, Acc) -> do_receive(Meta, X, Acc, EE) end, [], KV), {EClauses, elixir_env:mergev(EVars, E)}. do_receive(_Meta, {'do', nil} = Do, Acc, _E) -> {Do, Acc}; do_receive(Meta, {'do', _} = Do, Acc, E) -> Fun = expand_one(Meta, 'receive', 'do', fun head/2), expand_with_export(Meta, 'receive', Fun, Do, Acc, E); do_receive(Meta, {'after', [_]} = After, Acc, E) -> Fun = expand_one(Meta, 'receive', 'after', fun elixir_exp:expand_args/2), expand_with_export(Meta, 'receive', Fun, After, Acc, E); do_receive(Meta, {'after', _}, _Acc, E) -> compile_error(Meta, ?m(E, file), "expected a single -> clause for after in receive"); do_receive(Meta, {Key, _}, _Acc, E) -> compile_error(Meta, ?m(E, file), "unexpected keyword ~ts in receive", [Key]). %% Try 'try'(Meta, [], E) -> compile_error(Meta, ?m(E, file), "missing do keyword in try"); 'try'(Meta, [{do, _}], E) -> compile_error(Meta, ?m(E, file), "missing catch/rescue/after/else keyword in try"); 'try'(Meta, KV, E) when not is_list(KV) -> elixir_errors:compile_error(Meta, ?m(E, file), "invalid arguments for try"); 'try'(Meta, KV, E) -> {lists:map(fun(X) -> do_try(Meta, X, E) end, KV), E}. do_try(_Meta, {'do', Expr}, E) -> {EExpr, _} = elixir_exp:expand(Expr, E), {'do', EExpr}; do_try(_Meta, {'after', Expr}, E) -> {EExpr, _} = elixir_exp:expand(Expr, E), {'after', EExpr}; do_try(Meta, {'else', _} = Else, E) -> Fun = expand_one(Meta, 'try', 'else', fun head/2), expand_without_export(Meta, 'try', Fun, Else, E); do_try(Meta, {'catch', _} = Catch, E) -> expand_without_export(Meta, 'try', fun expand_catch/3, Catch, E); do_try(Meta, {'rescue', _} = Rescue, E) -> expand_without_export(Meta, 'try', fun expand_rescue/3, Rescue, E); do_try(Meta, {Key, _}, E) -> compile_error(Meta, ?m(E, file), "unexpected keyword ~ts in try", [Key]). expand_catch(_Meta, [_] = Args, E) -> head(Args, E); expand_catch(_Meta, [_, _] = Args, E) -> head(Args, E); expand_catch(Meta, _, E) -> compile_error(Meta, ?m(E, file), "expected one or two args for catch clauses (->) in try"). expand_rescue(Meta, [Arg], E) -> case expand_rescue(Arg, E) of {EArg, EA} -> {[EArg], EA}; false -> compile_error(Meta, ?m(E, file), "invalid rescue clause. The clause should " "match on an alias, a variable or be in the `var in [alias]` format") end; expand_rescue(Meta, _, E) -> compile_error(Meta, ?m(E, file), "expected one arg for rescue clauses (->) in try"). %% rescue var => var in _ expand_rescue({Name, _, Atom} = Var, E) when is_atom(Name), is_atom(Atom) -> expand_rescue({in, [], [Var, {'_', [], ?m(E, module)}]}, E); %% rescue var in [Exprs] expand_rescue({in, Meta, [Left, Right]}, E) -> {ELeft, EL} = match(fun elixir_exp:expand/2, Left, E), {ERight, ER} = elixir_exp:expand(Right, EL), case ELeft of {Name, _, Atom} when is_atom(Name), is_atom(Atom) -> case normalize_rescue(ERight) of false -> false; Other -> {{in, Meta, [ELeft, Other]}, ER} end; _ -> false end; %% rescue Error => _ in [Error] expand_rescue(Arg, E) -> expand_rescue({in, [], [{'_', [], ?m(E, module)}, Arg]}, E). normalize_rescue({'_', _, Atom} = N) when is_atom(Atom) -> N; normalize_rescue(Atom) when is_atom(Atom) -> [Atom]; normalize_rescue(Other) -> is_list(Other) andalso lists:all(fun is_atom/1, Other) andalso Other. %% Expansion helpers %% Returns a function that expands arguments %% considering we have at maximum one entry. expand_one(Meta, Kind, Key, Fun) -> fun ([_] = Args, E) -> Fun(Args, E); (_, E) -> compile_error(Meta, ?m(E, file), "expected one arg for ~ts clauses (->) in ~ts", [Key, Kind]) end. %% Expands all -> pairs in a given key keeping the overall vars. expand_with_export(Meta, Kind, Fun, {Key, Clauses}, Acc, E) when is_list(Clauses) -> EFun = case lists:keyfind(export_head, 1, Meta) of {export_head, true} -> Fun; _ -> fun(Args, #{export_vars := ExportVars} = EE) -> {FArgs, FE} = Fun(Args, EE), {FArgs, FE#{export_vars := ExportVars}} end end, Transformer = fun(Clause, Vars) -> {EClause, EC} = clause(Meta, Kind, EFun, Clause, E), {EClause, elixir_env:merge_vars(Vars, ?m(EC, export_vars))} end, {EClauses, EVars} = lists:mapfoldl(Transformer, Acc, Clauses), {{Key, EClauses}, EVars}; expand_with_export(Meta, Kind, _Fun, {Key, _}, _Acc, E) -> compile_error(Meta, ?m(E, file), "expected -> clauses for ~ts in ~ts", [Key, Kind]). %% Expands all -> pairs in a given key but do not keep the overall vars. expand_without_export(Meta, Kind, Fun, {Key, Clauses}, E) when is_list(Clauses) -> Transformer = fun(Clause) -> {EClause, _} = clause(Meta, Kind, Fun, Clause, E), EClause end, {Key, lists:map(Transformer, Clauses)}; expand_without_export(Meta, Kind, _Fun, {Key, _}, E) -> compile_error(Meta, ?m(E, file), "expected -> clauses for ~ts in ~ts", [Key, Kind]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_fn.erl000066400000000000000000000142741254730255300224410ustar00rootroot00000000000000-module(elixir_fn). -export([translate/3, capture/3, expand/3]). -import(elixir_errors, [compile_error/3, compile_error/4]). -include("elixir.hrl"). translate(Meta, Clauses, S) -> Transformer = fun({'->', CMeta, [ArgsWithGuards, Expr]}, Acc) -> {Args, Guards} = elixir_clauses:extract_splat_guards(ArgsWithGuards), {TClause, TS } = elixir_clauses:clause(?line(CMeta), fun translate_fn_match/2, Args, Expr, Guards, true, Acc), {TClause, elixir_scope:mergef(S, TS)} end, {TClauses, NS} = lists:mapfoldl(Transformer, S, Clauses), Arities = [length(Args) || {clause, _Line, Args, _Guards, _Exprs} <- TClauses], case lists:usort(Arities) of [_] -> {{'fun', ?line(Meta), {clauses, TClauses}}, NS}; _ -> compile_error(Meta, S#elixir_scope.file, "cannot mix clauses with different arities in function definition") end. translate_fn_match(Arg, S) -> {TArg, TS} = elixir_translator:translate_args(Arg, S#elixir_scope{backup_vars=orddict:new()}), {TArg, TS#elixir_scope{backup_vars=S#elixir_scope.backup_vars}}. %% Expansion expand(Meta, Clauses, E) when is_list(Clauses) -> Transformer = fun(Clause) -> {EClause, _} = elixir_exp_clauses:clause(Meta, fn, fun elixir_exp_clauses:head/2, Clause, E), EClause end, {{fn, Meta, lists:map(Transformer, Clauses)}, E}. %% Capture capture(Meta, {'/', _, [{{'.', _, [_, F]} = Dot, RequireMeta, []}, A]}, E) when is_atom(F), is_integer(A) -> Args = [{'&', [], [X]} || X <- lists:seq(1, A)], capture_require(Meta, {Dot, RequireMeta, Args}, E, true); capture(Meta, {'/', _, [{F, _, C}, A]}, E) when is_atom(F), is_integer(A), is_atom(C) -> ImportMeta = case lists:keyfind(import_fa, 1, Meta) of {import_fa, {Receiver, Context}} -> lists:keystore(context, 1, lists:keystore(import, 1, Meta, {import, Receiver}), {context, Context} ); false -> Meta end, Args = [{'&', [], [X]} || X <- lists:seq(1, A)], capture_import(Meta, {F, ImportMeta, Args}, E, true); capture(Meta, {{'.', _, [_, Fun]}, _, Args} = Expr, E) when is_atom(Fun), is_list(Args) -> capture_require(Meta, Expr, E, is_sequential_and_not_empty(Args)); capture(Meta, {{'.', _, [_]}, _, Args} = Expr, E) when is_list(Args) -> do_capture(Meta, Expr, E, false); capture(Meta, {'__block__', _, [Expr]}, E) -> capture(Meta, Expr, E); capture(Meta, {'__block__', _, _} = Expr, E) -> Message = "invalid args for &, block expressions are not allowed, got: ~ts", compile_error(Meta, ?m(E, file), Message, ['Elixir.Macro':to_string(Expr)]); capture(Meta, {Atom, _, Args} = Expr, E) when is_atom(Atom), is_list(Args) -> capture_import(Meta, Expr, E, is_sequential_and_not_empty(Args)); capture(Meta, {Left, Right}, E) -> capture(Meta, {'{}', Meta, [Left, Right]}, E); capture(Meta, List, E) when is_list(List) -> do_capture(Meta, List, E, is_sequential_and_not_empty(List)); capture(Meta, Arg, E) -> invalid_capture(Meta, Arg, E). capture_import(Meta, {Atom, ImportMeta, Args} = Expr, E, Sequential) -> Res = Sequential andalso elixir_dispatch:import_function(ImportMeta, Atom, length(Args), E), handle_capture(Res, Meta, Expr, E, Sequential). capture_require(Meta, {{'.', _, [Left, Right]}, RequireMeta, Args} = Expr, E, Sequential) -> {Mod, EE} = elixir_exp:expand(Left, E), Res = Sequential andalso case Mod of {Name, _, Context} when is_atom(Name), is_atom(Context) -> {remote, Mod, Right, length(Args)}; _ when is_atom(Mod) -> elixir_dispatch:require_function(RequireMeta, Mod, Right, length(Args), EE); _ -> false end, handle_capture(Res, Meta, Expr, EE, Sequential). handle_capture({local, Fun, Arity}, _Meta, _Expr, _E, _Sequential) -> {local, Fun, Arity}; handle_capture({remote, Receiver, Fun, Arity}, Meta, _Expr, E, _Sequential) -> Tree = {{'.', [], [erlang, make_fun]}, Meta, [Receiver, Fun, Arity]}, {expanded, Tree, E}; handle_capture(false, Meta, Expr, E, Sequential) -> do_capture(Meta, Expr, E, Sequential). do_capture(Meta, Expr, E, Sequential) -> case do_escape(Expr, elixir_counter:next(), E, []) of {_, []} when not Sequential -> invalid_capture(Meta, Expr, E); {EExpr, EDict} -> EVars = validate(Meta, EDict, 1, E), Fn = {fn, Meta, [{'->', Meta, [EVars, EExpr]}]}, {expanded, Fn, E} end. invalid_capture(Meta, Arg, E) -> Message = "invalid args for &, expected an expression in the format of &Mod.fun/arity, " "&local/arity or a capture containing at least one argument as &1, got: ~ts", compile_error(Meta, ?m(E, file), Message, ['Elixir.Macro':to_string(Arg)]). validate(Meta, [{Pos, Var}|T], Pos, E) -> [Var|validate(Meta, T, Pos + 1, E)]; validate(Meta, [{Pos, _}|_], Expected, E) -> compile_error(Meta, ?m(E, file), "capture &~B cannot be defined without &~B", [Pos, Expected]); validate(_Meta, [], _Pos, _E) -> []. do_escape({'&', _, [Pos]}, Counter, _E, Dict) when is_integer(Pos), Pos > 0 -> Var = {list_to_atom([$x, $@+Pos]), [{counter, Counter}], elixir_fn}, {Var, orddict:store(Pos, Var, Dict)}; do_escape({'&', Meta, [Pos]}, _Counter, E, _Dict) when is_integer(Pos) -> compile_error(Meta, ?m(E, file), "capture &~B is not allowed", [Pos]); do_escape({'&', Meta, _} = Arg, _Counter, E, _Dict) -> Message = "nested captures via & are not allowed: ~ts", compile_error(Meta, ?m(E, file), Message, ['Elixir.Macro':to_string(Arg)]); do_escape({Left, Meta, Right}, Counter, E, Dict0) -> {TLeft, Dict1} = do_escape(Left, Counter, E, Dict0), {TRight, Dict2} = do_escape(Right, Counter, E, Dict1), {{TLeft, Meta, TRight}, Dict2}; do_escape({Left, Right}, Counter, E, Dict0) -> {TLeft, Dict1} = do_escape(Left, Counter, E, Dict0), {TRight, Dict2} = do_escape(Right, Counter, E, Dict1), {{TLeft, TRight}, Dict2}; do_escape(List, Counter, E, Dict) when is_list(List) -> lists:mapfoldl(fun(X, Acc) -> do_escape(X, Counter, E, Acc) end, Dict, List); do_escape(Other, _Counter, _E, Dict) -> {Other, Dict}. is_sequential_and_not_empty([]) -> false; is_sequential_and_not_empty(List) -> is_sequential(List, 1). is_sequential([{'&', _, [Int]}|T], Int) -> is_sequential(T, Int + 1); is_sequential([], _Int) -> true; is_sequential(_, _Int) -> false. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_for.erl000066400000000000000000000240201254730255300226120ustar00rootroot00000000000000-module(elixir_for). -export([expand/3, translate/3]). -include("elixir.hrl"). %% Expansion expand(Meta, Args, E) -> {Cases, Block} = case elixir_utils:split_last(Args) of {OuterCases, OuterOpts} when is_list(OuterOpts) -> case elixir_utils:split_last(OuterCases) of {InnerCases, InnerOpts} when is_list(InnerOpts) -> {InnerCases, InnerOpts ++ OuterOpts}; _ -> {OuterCases, OuterOpts} end; _ -> {Args, []} end, {Expr, Opts} = case lists:keyfind(do, 1, Block) of {do, Do} -> {Do, lists:keydelete(do, 1, Block)}; _ -> elixir_errors:compile_error(Meta, ?m(E, file), "missing do keyword in for comprehension") end, {EOpts, EO} = elixir_exp:expand(Opts, E), {ECases, EC} = lists:mapfoldl(fun expand/2, EO, Cases), {EExpr, _} = elixir_exp:expand(Expr, EC), {{for, Meta, ECases ++ [[{do, EExpr}|EOpts]]}, E}. expand({'<-', Meta, [Left, Right]}, E) -> {ERight, ER} = elixir_exp:expand(Right, E), {ELeft, EL} = elixir_exp_clauses:match(fun elixir_exp:expand/2, Left, E), {{'<-', Meta, [ELeft, ERight]}, elixir_env:mergev(EL, ER)}; expand({'<<>>', Meta, Args} = X, E) when is_list(Args) -> case elixir_utils:split_last(Args) of {LeftStart, {'<-', OpMeta, [LeftEnd, Right]}} -> {ERight, ER} = elixir_exp:expand(Right, E), Left = {'<<>>', Meta, LeftStart ++ [LeftEnd]}, {ELeft, EL} = elixir_exp_clauses:match(fun elixir_exp:expand/2, Left, E), {{'<<>>', [], [ {'<-', OpMeta, [ELeft, ERight]}]}, elixir_env:mergev(EL, ER)}; _ -> elixir_exp:expand(X, E) end; expand(X, E) -> elixir_exp:expand(X, E). %% Translation translate(Meta, Args, #elixir_scope{return=Return} = RS) -> S = RS#elixir_scope{return=true}, {AccName, _, SA} = elixir_scope:build_var('_', S), {VarName, _, SV} = elixir_scope:build_var('_', SA), Line = ?line(Meta), Acc = {var, Line, AccName}, Var = {var, Line, VarName}, {Cases, [{do, Expr}|Opts]} = elixir_utils:split_last(Args), {TInto, SI} = case lists:keyfind(into, 1, Opts) of {into, Into} -> elixir_translator:translate(Into, SV); false when Return -> {{nil, Line}, SV}; false -> {false, SV} end, {TCases, SC} = translate_gen(Meta, Cases, [], SI), {TExpr, SE} = elixir_translator:translate_block(Expr, Return, SC), SF = elixir_scope:mergec(SI, SE), case comprehension_expr(TInto, TExpr) of {inline, TIntoExpr} -> {build_inline(Line, TCases, TIntoExpr, TInto, Var, Acc, SE), SF}; {into, TIntoExpr} -> build_into(Line, TCases, TIntoExpr, TInto, Var, Acc, SF) end. translate_gen(ForMeta, [{'<-', Meta, [Left, Right]}|T], Acc, S) -> {TLeft, TRight, TFilters, TT, TS} = translate_gen(Meta, Left, Right, T, S), TAcc = [{enum, Meta, TLeft, TRight, TFilters}|Acc], translate_gen(ForMeta, TT, TAcc, TS); translate_gen(ForMeta, [{'<<>>', _, [ {'<-', Meta, [Left, Right]} ]}|T], Acc, S) -> {TLeft, TRight, TFilters, TT, TS} = translate_gen(Meta, Left, Right, T, S), TAcc = [{bin, Meta, TLeft, TRight, TFilters}|Acc], case elixir_bitstring:has_size(TLeft) of true -> translate_gen(ForMeta, TT, TAcc, TS); false -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "bitstring fields without size are not allowed in bitstring generators") end; translate_gen(_ForMeta, [], Acc, S) -> {lists:reverse(Acc), S}; translate_gen(ForMeta, _, _, S) -> elixir_errors:compile_error(ForMeta, S#elixir_scope.file, "for comprehensions must start with a generator"). translate_gen(_Meta, Left, Right, T, S) -> {TRight, SR} = elixir_translator:translate(Right, S), {TLeft, SL} = elixir_clauses:match(fun elixir_translator:translate/2, Left, SR), {TT, {TFilters, TS}} = translate_filters(T, SL), {TLeft, TRight, TFilters, TT, TS}. translate_filters(T, S) -> {Filters, Rest} = collect_filters(T, []), {Rest, lists:mapfoldr(fun translate_filter/2, S, Filters)}. translate_filter(Filter, S) -> {TFilter, TS} = elixir_translator:translate(Filter, S), case elixir_utils:returns_boolean(Filter) of true -> {{nil, TFilter}, TS}; false -> {Name, _, VS} = elixir_scope:build_var('_', TS), {{{var, 0, Name}, TFilter}, VS} end. collect_filters([{'<-', _, [_, _]}|_] = T, Acc) -> {Acc, T}; collect_filters([{'<<>>', _, [{'<-', _, [_, _]}]}|_] = T, Acc) -> {Acc, T}; collect_filters([H|T], Acc) -> collect_filters(T, [H|Acc]); collect_filters([], Acc) -> {Acc, []}. build_inline(Line, Clauses, Expr, Into, _Var, Acc, S) -> case lists:all(fun(Clause) -> element(1, Clause) == bin end, Clauses) of true -> build_comprehension(Line, Clauses, Expr, Into); false -> build_reduce(Clauses, Expr, Into, Acc, S) end. build_into(Line, Clauses, Expr, Into, Fun, Acc, S) -> {Kind, SK} = build_var(Line, S), {Reason, SR} = build_var(Line, SK), {Stack, ST} = build_var(Line, SR), {Done, SD} = build_var(Line, ST), IntoExpr = {call, Line, Fun, [Acc, pair(Line, cont, Expr)]}, MatchExpr = {match, Line, {tuple, Line, [Acc, Fun]}, elixir_utils:erl_call(Line, 'Elixir.Collectable', into, [Into]) }, TryExpr = {'try', Line, [build_reduce_clause(Clauses, IntoExpr, Acc, Acc, SD)], [{clause, Line, [Done], [], [{call, Line, Fun, [Done, {atom, Line, done}]}]}], [{clause, Line, [{tuple, Line, [Kind, Reason, {var, Line, '_'}]}], [], [{match, Line, Stack, elixir_utils:erl_call(Line, erlang, get_stacktrace, [])}, {call, Line, Fun, [Acc, {atom, Line, halt}]}, elixir_utils:erl_call(Line, erlang, raise, [Kind, Reason, Stack])]}], []}, {{block, Line, [MatchExpr, TryExpr]}, SD}. %% Helpers build_reduce(Clauses, Expr, false, Acc, S) -> build_reduce_clause(Clauses, Expr, {nil, 0}, Acc, S); build_reduce(Clauses, Expr, {nil, Line} = Into, Acc, S) -> ListExpr = {cons, Line, Expr, Acc}, elixir_utils:erl_call(Line, lists, reverse, [build_reduce_clause(Clauses, ListExpr, Into, Acc, S)]); build_reduce(Clauses, Expr, {bin, _, _} = Into, Acc, S) -> {bin, Line, Elements} = Expr, BinExpr = {bin, Line, [{bin_element, Line, Acc, default, [bitstring]}|Elements]}, build_reduce_clause(Clauses, BinExpr, Into, Acc, S). build_reduce_clause([{enum, Meta, Left, Right, Filters}|T], Expr, Arg, Acc, S) -> Line = ?line(Meta), True = build_reduce_clause(T, Expr, Acc, Acc, S), False = Acc, Clauses0 = case is_var(Left) of true -> []; false -> [{clause, -1, [{var, Line, '_'}, Acc], [], [False]}] end, Clauses1 = [{clause, Line, [Left, Acc], [], [join_filters(Line, Filters, True, False)]}|Clauses0], Args = [Right, Arg, {'fun', Line, {clauses, Clauses1}}], elixir_utils:erl_call(Line, 'Elixir.Enum', reduce, Args); build_reduce_clause([{bin, Meta, Left, Right, Filters}|T], Expr, Arg, Acc, S) -> Line = ?line(Meta), {Tail, ST} = build_var(Line, S), {Fun, SF} = build_var(Line, ST), True = build_reduce_clause(T, Expr, Acc, Acc, SF), False = Acc, {bin, _, Elements} = Left, BinMatch = {bin, Line, Elements ++ [{bin_element, Line, Tail, default, [bitstring]}]}, NoVarMatch = {bin, Line, no_var(Elements) ++ [{bin_element, Line, Tail, default, [bitstring]}]}, Clauses = [{clause, Line, [BinMatch, Acc], [], [{call, Line, Fun, [Tail, join_filters(Line, Filters, True, False)]}]}, {clause, -1, [NoVarMatch, Acc], [], [{call, Line, Fun, [Tail, False]}]}, {clause, -1, [{bin, Line, []}, Acc], [], [Acc]}, {clause, -1, [Tail, {var, Line, '_'}], [], [elixir_utils:erl_call(Line, erlang, error, [pair(Line, badarg, Tail)])]}], {call, Line, {named_fun, Line, element(3, Fun), Clauses}, [Right, Arg]}; build_reduce_clause([], Expr, _Arg, _Acc, _S) -> Expr. is_var({var, _, _}) -> true; is_var(_) -> false. pair(Line, Atom, Arg) -> {tuple, Line, [{atom, Line, Atom}, Arg]}. build_var(Line, S) -> {Name, _, ST} = elixir_scope:build_var('_', S), {{var, Line, Name}, ST}. no_var(Elements) -> [{bin_element, Line, no_var_expr(Expr), Size, Types} || {bin_element, Line, Expr, Size, Types} <- Elements]. no_var_expr({var, Line, _}) -> {var, Line, '_'}. build_comprehension(Line, Clauses, Expr, false) -> {block, Line, [ build_comprehension(Line, Clauses, Expr, {nil, Line}), {nil, Line} ]}; build_comprehension(Line, Clauses, Expr, Into) -> {comprehension_kind(Into), Line, Expr, comprehension_clause(Clauses)}. comprehension_clause([{Kind, Meta, Left, Right, Filters}|T]) -> Line = ?line(Meta), [{comprehension_generator(Kind), Line, Left, Right}] ++ comprehension_filter(Line, Filters) ++ comprehension_clause(T); comprehension_clause([]) -> []. comprehension_kind({nil, _}) -> lc; comprehension_kind({bin, _, []}) -> bc. comprehension_generator(enum) -> generate; comprehension_generator(bin) -> b_generate. comprehension_expr({bin, _, []}, {bin, _, _} = Expr) -> {inline, Expr}; comprehension_expr({bin, Line, []}, Expr) -> BinExpr = {bin, Line, [{bin_element, Line, Expr, default, [bitstring]}]}, {inline, BinExpr}; comprehension_expr({nil, _}, Expr) -> {inline, Expr}; comprehension_expr(false, Expr) -> {inline, Expr}; comprehension_expr(_, Expr) -> {into, Expr}. comprehension_filter(Line, Filters) -> [join_filter(Line, Filter, {atom, Line, true}, {atom, Line, false}) || Filter <- lists:reverse(Filters)]. join_filters(_Line, [], True, _False) -> True; join_filters(Line, [H|T], True, False) -> lists:foldl(fun(Filter, Acc) -> join_filter(Line, Filter, Acc, False) end, join_filter(Line, H, True, False), T). join_filter(Line, {nil, Filter}, True, False) -> {'case', Line, Filter, [ {clause, Line, [{atom, Line, true}], [], [True]}, {clause, Line, [{atom, Line, false}], [], [False]} ]}; join_filter(Line, {Var, Filter}, True, False) -> Guard = {op, Line, 'orelse', {op, Line, '==', Var, {atom, Line, false}}, {op, Line, '==', Var, {atom, Line, nil}}}, {'case', Line, Filter, [ {clause, Line, [Var], [[Guard]], [False]}, {clause, Line, [{var, Line, '_'}], [], [True]} ]}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_import.erl000066400000000000000000000136271254730255300233510ustar00rootroot00000000000000%% Module responsible for handling imports and conflicts %% between local functions and imports. %% For imports dispatch, please check elixir_dispatch. -module(elixir_import). -export([import/4, special_form/2, format_error/1]). -include("elixir.hrl"). %% IMPORT import(Meta, Ref, Opts, E) -> Res = case keyfind(only, Opts) of {only, functions} -> {import_functions(Meta, Ref, Opts, E), ?m(E, macros)}; {only, macros} -> {?m(E, functions), import_macros(true, Meta, Ref, Opts, E)}; {only, List} when is_list(List) -> {import_functions(Meta, Ref, Opts, E), import_macros(false, Meta, Ref, Opts, E)}; false -> {import_functions(Meta, Ref, Opts, E), import_macros(false, Meta, Ref, Opts, E)} end, record_warn(Meta, Ref, Opts, E), Res. import_functions(Meta, Ref, Opts, E) -> calculate(Meta, Ref, Opts, ?m(E, functions), E, fun() -> get_functions(Ref) end). import_macros(Force, Meta, Ref, Opts, E) -> calculate(Meta, Ref, Opts, ?m(E, macros), E, fun() -> case Force of true -> get_macros(Meta, Ref, E); false -> get_optional_macros(Ref) end end). record_warn(Meta, Ref, Opts, E) -> Warn = case keyfind(warn, Opts) of {warn, false} -> false; {warn, true} -> true; false -> not lists:keymember(context, 1, Meta) end, elixir_lexical:record_import(Ref, ?line(Meta), Warn, ?m(E, lexical_tracker)). %% Calculates the imports based on only and except calculate(Meta, Key, Opts, Old, E, Existing) -> New = case keyfind(only, Opts) of {only, Only} when is_list(Only) -> case Only -- get_exports(Key) of [{Name, Arity}|_] -> Tuple = {invalid_import, {Key, Name, Arity}}, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, Tuple); _ -> intersection(Only, Existing()) end; _ -> case keyfind(except, Opts) of false -> remove_underscored(Existing()); {except, Except} when is_list(Except) -> case keyfind(Key, Old) of false -> remove_underscored(Existing()) -- Except; {Key, OldImports} -> OldImports -- Except end end end, %% Normalize the data before storing it Set = ordsets:from_list(New), Final = remove_internals(Set), case Final of [] -> keydelete(Key, Old); _ -> ensure_no_special_form_conflict(Meta, ?m(E, file), Key, Final), [{Key, Final}|keydelete(Key, Old)] end. %% Retrieve functions and macros from modules get_exports(Module) -> try Module:'__info__'(functions) ++ Module:'__info__'(macros) catch error:undef -> Module:module_info(exports) end. get_functions(Module) -> try Module:'__info__'(functions) catch error:undef -> Module:module_info(exports) end. get_macros(Meta, Module, E) -> try Module:'__info__'(macros) catch error:undef -> Tuple = {no_macros, Module}, elixir_errors:form_error(Meta, ?m(E, file), ?MODULE, Tuple) end. get_optional_macros(Module) -> case code:ensure_loaded(Module) of {module, Module} -> try Module:'__info__'(macros) catch error:undef -> [] end; {error, _} -> [] end. %% VALIDATION HELPERS ensure_no_special_form_conflict(Meta, File, Key, [{Name, Arity}|T]) -> case special_form(Name, Arity) of true -> Tuple = {special_form_conflict, {Key, Name, Arity}}, elixir_errors:form_error(Meta, File, ?MODULE, Tuple); false -> ensure_no_special_form_conflict(Meta, File, Key, T) end; ensure_no_special_form_conflict(_Meta, _File, _Key, []) -> ok. %% ERROR HANDLING format_error({invalid_import, {Receiver, Name, Arity}}) -> io_lib:format("cannot import ~ts.~ts/~B because it doesn't exist", [elixir_aliases:inspect(Receiver), Name, Arity]); format_error({special_form_conflict, {Receiver, Name, Arity}}) -> io_lib:format("cannot import ~ts.~ts/~B because it conflicts with Elixir special forms", [elixir_aliases:inspect(Receiver), Name, Arity]); format_error({no_macros, Module}) -> io_lib:format("could not load macros from module ~ts", [elixir_aliases:inspect(Module)]). %% LIST HELPERS keyfind(Key, List) -> lists:keyfind(Key, 1, List). keydelete(Key, List) -> lists:keydelete(Key, 1, List). intersection([H|T], All) -> case lists:member(H, All) of true -> [H|intersection(T, All)]; false -> intersection(T, All) end; intersection([], _All) -> []. %% Internal funs that are never imported etc. remove_underscored(List) -> lists:filter(fun({Name, _}) -> case atom_to_list(Name) of "_" ++ _ -> false; _ -> true end end, List). remove_internals(Set) -> ordsets:del_element({module_info, 1}, ordsets:del_element({module_info, 0}, Set)). %% Special forms special_form('&', 1) -> true; special_form('^', 1) -> true; special_form('=', 2) -> true; special_form('%', 2) -> true; special_form('::', 2) -> true; special_form('__op__', 2) -> true; special_form('__op__', 3) -> true; special_form('__block__', _) -> true; special_form('->', _) -> true; special_form('<<>>', _) -> true; special_form('{}', _) -> true; special_form('%{}', _) -> true; special_form('alias', 1) -> true; special_form('alias', 2) -> true; special_form('require', 1) -> true; special_form('require', 2) -> true; special_form('import', 1) -> true; special_form('import', 2) -> true; special_form('__ENV__', 0) -> true; special_form('__CALLER__', 0) -> true; special_form('__MODULE__', 0) -> true; special_form('__DIR__', 0) -> true; special_form('__aliases__', _) -> true; special_form('quote', 1) -> true; special_form('quote', 2) -> true; special_form('unquote', 1) -> true; special_form('unquote_splicing', 1) -> true; special_form('fn', _) -> true; special_form('super', _) -> true; special_form('for', _) -> true; special_form('cond', 1) -> true; special_form('case', 2) -> true; special_form('try', 2) -> true; special_form('receive', 1) -> true; special_form(_, _) -> false. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_interpolation.erl000066400000000000000000000144161254730255300247230ustar00rootroot00000000000000% Handle string and string-like interpolations. -module(elixir_interpolation). -export([extract/6, unescape_chars/1, unescape_chars/2, unescape_tokens/1, unescape_tokens/2, unescape_map/1]). -include("elixir.hrl"). %% Extract string interpolations extract(Line, Column, Raw, Interpol, String, Last) -> %% Ignore whatever is in the scope and enable terminator checking. Scope = Raw#elixir_tokenizer{terminators=[], check_terminators=true}, extract(Line, Column, Scope, Interpol, String, [], [], Last). %% Terminators extract(Line, Column, _Scope, _Interpol, [], Buffer, Output, []) -> finish_extraction(Line, Column, Buffer, Output, []); extract(Line, _Column, _Scope, _Interpol, [], _Buffer, _Output, Last) -> {error, {string, Line, io_lib:format("missing terminator: ~ts", [[Last]]), []}}; extract(Line, Column, _Scope, _Interpol, [Last|Remaining], Buffer, Output, Last) -> finish_extraction(Line, Column + 1, Buffer, Output, Remaining); %% Going through the string extract(Line, _Column, Scope, Interpol, [$\\, $\n|Rest], Buffer, Output, Last) -> extract(Line+1, 1, Scope, Interpol, Rest, Buffer, Output, Last); extract(Line, _Column, Scope, Interpol, [$\\, $\r, $\n|Rest], Buffer, Output, Last) -> extract(Line+1, 1, Scope, Interpol, Rest, Buffer, Output, Last); extract(Line, _Column, Scope, Interpol, [$\n|Rest], Buffer, Output, Last) -> extract(Line+1, 1, Scope, Interpol, Rest, [$\n|Buffer], Output, Last); extract(Line, Column, Scope, Interpol, [$\\, Last|Rest], Buffer, Output, Last) -> extract(Line, Column+2, Scope, Interpol, Rest, [Last|Buffer], Output, Last); extract(Line, Column, Scope, true, [$\\, $#, ${|Rest], Buffer, Output, Last) -> extract(Line, Column+1, Scope, true, Rest, [${, $#|Buffer], Output, Last); extract(Line, Column, Scope, true, [$#, ${|Rest], Buffer, Output, Last) -> Output1 = build_string(Line, Buffer, Output), case elixir_tokenizer:tokenize(Rest, Line, Column + 2, Scope) of {error, {{EndLine, _, EndColumn}, _, "}"}, [$}|NewRest], Tokens} -> Output2 = build_interpol(Line, Column, EndColumn, Tokens, Output1), extract(EndLine, EndColumn, Scope, true, NewRest, [], Output2, Last); {error, Reason, _, _} -> {error, Reason}; {ok, _EndLine, _EndColumn, _} -> {error, {string, Line, "missing interpolation terminator:}", []}} end; extract(Line, Column, Scope, Interpol, [$\\, Char|Rest], Buffer, Output, Last) -> extract(Line, Column+2, Scope, Interpol, Rest, [Char, $\\|Buffer], Output, Last); %% Catch all clause extract(Line, Column, Scope, Interpol, [Char|Rest], Buffer, Output, Last) -> extract(Line, Column + 1, Scope, Interpol, Rest, [Char|Buffer], Output, Last). %% Unescape a series of tokens as returned by extract. unescape_tokens(Tokens) -> unescape_tokens(Tokens, fun unescape_map/1). unescape_tokens(Tokens, Map) -> [unescape_token(Token, Map) || Token <- Tokens]. unescape_token(Token, Map) when is_binary(Token) -> unescape_chars(Token, Map); unescape_token(Other, _Map) -> Other. % Unescape chars. For instance, "\" "n" (two chars) needs to be converted to "\n" (one char). unescape_chars(String) -> unescape_chars(String, fun unescape_map/1). unescape_chars(String, Map) -> unescape_chars(String, Map, Map($x) == true, <<>>). unescape_chars(<<$\\, $x, A, B, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B) -> append_escaped(Rest, Map, [A, B], true, Acc, 16); unescape_chars(<<$\\, $x, A, Rest/binary>>, Map, true, Acc) when ?is_hex(A) -> append_escaped(Rest, Map, [A], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A) -> append_escaped(Rest, Map, [A], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,B,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B) -> append_escaped(Rest, Map, [A, B], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,B,C,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B), ?is_hex(C) -> append_escaped(Rest, Map, [A, B, C], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,B,C,D,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D) -> append_escaped(Rest, Map, [A, B, C, D], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,B,C,D,E,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D), ?is_hex(E) -> append_escaped(Rest, Map, [A, B, C, D, E], true, Acc, 16); unescape_chars(<<$\\, $x, ${,A,B,C,D,E,F,$}, Rest/binary>>, Map, true, Acc) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D), ?is_hex(E), ?is_hex(F) -> append_escaped(Rest, Map, [A, B, C, D, E, F], true, Acc, 16); unescape_chars(<<$\\, $x, _/binary>>, _Map, true, _Acc) -> Msg = <<"missing hex sequence after \\x">>, error('Elixir.ArgumentError':exception([{message, Msg}])); unescape_chars(<<$\\, Escaped, Rest/binary>>, Map, Hex, Acc) -> case Map(Escaped) of false -> unescape_chars(Rest, Map, Hex, <>); Other -> unescape_chars(Rest, Map, Hex, <>) end; unescape_chars(<>, Map, Hex, Acc) -> unescape_chars(Rest, Map, Hex, <>); unescape_chars(<<>>, _Map, _Hex, Acc) -> Acc. append_escaped(Rest, Map, List, Hex, Acc, Base) -> Codepoint = list_to_integer(List, Base), try <> of Binary -> unescape_chars(Rest, Map, Hex, Binary) catch error:badarg -> Msg = <<"invalid or reserved unicode codepoint ", (integer_to_binary(Codepoint))/binary>>, error('Elixir.ArgumentError':exception([{message, Msg}])) end. % Unescape Helpers unescape_map($0) -> 0; unescape_map($a) -> 7; unescape_map($b) -> $\b; unescape_map($d) -> $\d; unescape_map($e) -> $\e; unescape_map($f) -> $\f; unescape_map($n) -> $\n; unescape_map($r) -> $\r; unescape_map($s) -> $\s; unescape_map($t) -> $\t; unescape_map($v) -> $\v; unescape_map($x) -> true; unescape_map(E) -> E. % Extract Helpers finish_extraction(Line, Column, Buffer, Output, Remaining) -> case build_string(Line, Buffer, Output) of [] -> Final = [<<>>]; Final -> [] end, {Line, Column, lists:reverse(Final), Remaining}. build_string(_Line, [], Output) -> Output; build_string(_Line, Buffer, Output) -> [elixir_utils:characters_to_binary(lists:reverse(Buffer))|Output]. build_interpol(Line, Column, EndColumn, Buffer, Output) -> [{{Line, Column, EndColumn}, lists:reverse(Buffer)}|Output]. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_lexical.erl000066400000000000000000000037611254730255300234560ustar00rootroot00000000000000%% Module responsible for tracking lexical information. -module(elixir_lexical). -export([run/3, dest/1, record_alias/4, record_alias/2, record_import/4, record_import/2, record_remote/2, format_error/1 ]). -include("elixir.hrl"). -define(tracker, 'Elixir.Kernel.LexicalTracker'). run(File, Dest, Callback) -> case elixir_compiler:get_opt(internal) of false -> {ok, Pid} = ?tracker:start_link(Dest), try Callback(Pid) of Res -> warn_unused_aliases(File, Pid), warn_unused_imports(File, Pid), Res after unlink(Pid), ?tracker:stop(Pid) end; true -> Callback(nil) end. dest(nil) -> nil; dest(Pid) -> ?tracker:dest(Pid). %% RECORD record_alias(Module, Line, Warn, Ref) -> if_tracker(Ref, fun(Pid) -> ?tracker:add_alias(Pid, Module, Line, Warn), ok end). record_import(Module, Line, Warn, Ref) -> if_tracker(Ref, fun(Pid) -> ?tracker:add_import(Pid, Module, Line, Warn), ok end). record_alias(Module, Ref) -> if_tracker(Ref, fun(Pid) -> ?tracker:alias_dispatch(Pid, Module), ok end). record_import(Module, Ref) -> if_tracker(Ref, fun(Pid) -> ?tracker:import_dispatch(Pid, Module), ok end). record_remote(Module, Ref) -> if_tracker(Ref, fun(Pid) -> ?tracker:remote_dispatch(Pid, Module), ok end). %% HELPERS if_tracker(nil, _Callback) -> ok; if_tracker(Pid, Callback) when is_pid(Pid) -> Callback(Pid). %% ERROR HANDLING warn_unused_imports(File, Pid) -> [begin elixir_errors:form_warn([{line, L}], File, ?MODULE, {unused_import, M}) end || {M, L} <- ?tracker:collect_unused_imports(Pid)], ok. warn_unused_aliases(File, Pid) -> [begin elixir_errors:form_warn([{line, L}], File, ?MODULE, {unused_alias, M}) end || {M, L} <- ?tracker:collect_unused_aliases(Pid)], ok. format_error({unused_alias, Module}) -> io_lib:format("unused alias ~ts", [elixir_aliases:inspect(Module)]); format_error({unused_import, Module}) -> io_lib:format("unused import ~ts", [elixir_aliases:inspect(Module)]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_locals.erl000066400000000000000000000133741254730255300233130ustar00rootroot00000000000000%% Module responsible for tracking invocations of module calls. -module(elixir_locals). -export([ setup/1, cleanup/1, cache_env/1, get_cached_env/1, record_local/2, record_local/3, record_import/4, record_definition/3, record_defaults/4, ensure_no_import_conflict/4, warn_unused_local/3, format_error/1 ]). -export([macro_for/3, local_for/3, local_for/4]). -include("elixir.hrl"). -define(attr, {elixir, locals_tracker}). -define(tracker, 'Elixir.Module.LocalsTracker'). macro_for(Module, Name, Arity) -> Tuple = {Name, Arity}, try elixir_def:lookup_definition(Module, Tuple) of {{Tuple, Kind, Line, _, _, _, _}, [_|_] = Clauses} when Kind == defmacro; Kind == defmacrop -> fun() -> get_function(Line, Module, Clauses) end; _ -> false catch error:badarg -> false end. local_for(Module, Name, Arity) -> local_for(Module, Name, Arity, nil). local_for(Module, Name, Arity, Given) -> Tuple = {Name, Arity}, case elixir_def:lookup_definition(Module, Tuple) of {{Tuple, Kind, Line, _, _, _, _}, [_|_] = Clauses} when Given == nil; Kind == Given -> get_function(Line, Module, Clauses); _ -> [_|T] = erlang:get_stacktrace(), erlang:raise(error, undef, [{Module, Name, Arity, []}|T]) end. get_function(Line, Module, Clauses) -> RewrittenClauses = [rewrite_clause(Clause, Module) || Clause <- Clauses], Fun = {'fun', Line, {clauses, RewrittenClauses}}, {value, Result, _Binding} = erl_eval:exprs([Fun], []), Result. rewrite_clause({call, Line, {atom, Line, RawName}, Args}, Module) -> Remote = {remote, Line, {atom, Line, ?MODULE}, {atom, Line, local_for} }, %% If we have a macro, its arity in the table is %% actually one less than in the function call {Name, Arity} = case atom_to_list(RawName) of "MACRO-" ++ Rest -> {list_to_atom(Rest), length(Args) - 1}; _ -> {RawName, length(Args)} end, FunCall = {call, Line, Remote, [ {atom, Line, Module}, {atom, Line, Name}, {integer, Line, Arity} ]}, {call, Line, FunCall, Args}; rewrite_clause(Tuple, Module) when is_tuple(Tuple) -> list_to_tuple(rewrite_clause(tuple_to_list(Tuple), Module)); rewrite_clause(List, Module) when is_list(List) -> [rewrite_clause(Item, Module) || Item <- List]; rewrite_clause(Else, _) -> Else. %% TRACKING setup(Module) -> case elixir_compiler:get_opt(internal) of false -> {ok, Pid} = ?tracker:start_link(), ets:insert(elixir_module:data_table(Module), {?attr, Pid}), ok; true -> ok end. cleanup(Module) -> if_tracker(Module, fun(Pid) -> unlink(Pid), ?tracker:stop(Pid), ok end). record_local(Tuple, Module) when is_atom(Module) -> if_tracker(Module, fun(Pid) -> ?tracker:add_local(Pid, Tuple), ok end). record_local(Tuple, _Module, Function) when Function == nil; Function == Tuple -> ok; record_local(Tuple, Module, Function) -> if_tracker(Module, fun(Pid) -> ?tracker:add_local(Pid, Function, Tuple), ok end). record_import(_Tuple, Receiver, Module, _Function) when Module == nil; Module == Receiver -> false; record_import(Tuple, Receiver, Module, Function) -> if_tracker(Module, fun(Pid) -> ?tracker:add_import(Pid, Function, Receiver, Tuple), ok end). record_definition(Tuple, Kind, Module) -> if_tracker(Module, fun(Pid) -> ?tracker:add_definition(Pid, Kind, Tuple), ok end). record_defaults(_Tuple, _Kind, _Module, 0) -> ok; record_defaults(Tuple, Kind, Module, Defaults) -> if_tracker(Module, fun(Pid) -> ?tracker:add_defaults(Pid, Kind, Tuple, Defaults), ok end). if_tracker(Module, Callback) -> if_tracker(Module, ok, Callback). if_tracker(Module, Default, Callback) -> try ets:lookup_element(elixir_module:data_table(Module), ?attr, 2) of Pid -> Callback(Pid) catch error:badarg -> Default end. %% CACHING cache_env(#{module := Module} = RE) -> E = RE#{line := nil, vars := []}, try ets:lookup_element(elixir_module:data_table(Module), ?attr, 2) of Pid -> {Pid, ?tracker:cache_env(Pid, E)} catch error:badarg -> {Escaped, _} = elixir_quote:escape(E, false), Escaped end. get_cached_env({Pid, Ref}) -> ?tracker:get_cached_env(Pid, Ref); get_cached_env(Env) -> Env. %% ERROR HANDLING ensure_no_import_conflict(_Line, _File, 'Elixir.Kernel', _All) -> ok; ensure_no_import_conflict(Line, File, Module, All) -> if_tracker(Module, ok, fun(Pid) -> _ = [ begin elixir_errors:form_error([{line, Line}], File, ?MODULE, {function_conflict, Error}) end || Error <- ?tracker:collect_imports_conflicts(Pid, All) ], ok end). warn_unused_local(File, Module, Private) -> if_tracker(Module, [], fun(Pid) -> Args = [{Fun, Kind, Defaults} || {Fun, Kind, _Line, true, Defaults} <- Private], {Unreachable, Warnings} = ?tracker:collect_unused_locals(Pid, Args), [begin {_, _, Line, _, _} = lists:keyfind(element(2, Error), 1, Private), elixir_errors:form_warn([{line, Line}], File, ?MODULE, Error) end || Error <- Warnings ], Unreachable end). format_error({function_conflict, {Receivers, Name, Arity}}) -> io_lib:format("imported ~ts.~ts/~B conflicts with local function", [elixir_aliases:inspect(hd(Receivers)), Name, Arity]); format_error({unused_args, {Name, Arity}}) -> io_lib:format("default arguments in ~ts/~B are never used", [Name, Arity]); format_error({unused_args, {Name, Arity}, 1}) -> io_lib:format("the first default argument in ~ts/~B is never used", [Name, Arity]); format_error({unused_args, {Name, Arity}, Count}) -> io_lib:format("the first ~B default arguments in ~ts/~B are never used", [Count, Name, Arity]); format_error({unused_def, {Name, Arity}, defp}) -> io_lib:format("function ~ts/~B is unused", [Name, Arity]); format_error({unused_def, {Name, Arity}, defmacrop}) -> io_lib:format("macro ~ts/~B is unused", [Name, Arity]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_map.erl000066400000000000000000000137651254730255300226170ustar00rootroot00000000000000-module(elixir_map). -export([expand_map/3, translate_map/3, expand_struct/4, translate_struct/4]). -import(elixir_errors, [compile_error/4]). -include("elixir.hrl"). expand_map(Meta, [{'|', UpdateMeta, [Left, Right]}], E) -> {[ELeft|ERight], EA} = elixir_exp:expand_args([Left|Right], E), validate_kv(Meta, ERight, Right, E), {{'%{}', Meta, [{'|', UpdateMeta, [ELeft, ERight]}]}, EA}; expand_map(Meta, Args, E) -> {EArgs, EA} = elixir_exp:expand_args(Args, E), validate_kv(Meta, EArgs, Args, E), {{'%{}', Meta, EArgs}, EA}. expand_struct(Meta, Left, Right, E) -> {[ELeft, ERight], EE} = elixir_exp:expand_args([Left, Right], E), case is_atom(ELeft) of true -> ok; false -> compile_error(Meta, ?m(E, file), "expected struct name to be a compile " "time atom or alias, got: ~ts", ['Elixir.Macro':to_string(ELeft)]) end, EMeta = case lists:member(ELeft, ?m(E, context_modules)) of true -> [{struct, context}|Meta]; false -> Meta end, case ERight of {'%{}', _, _} -> ok; _ -> compile_error(Meta, ?m(E, file), "expected struct to be followed by a map, got: ~ts", ['Elixir.Macro':to_string(ERight)]) end, {{'%', EMeta, [ELeft, ERight]}, EE}. validate_kv(Meta, KV, Original, E) -> lists:foldl(fun ({_K, _V}, Acc) -> Acc + 1; (_, Acc) -> compile_error(Meta, ?m(E, file), "expected key-value pairs in a map, got: ~ts", ['Elixir.Macro':to_string(lists:nth(Acc, Original))]) end, 1, KV). translate_map(Meta, Args, S) -> {Assocs, TUpdate, US} = extract_assoc_update(Args, S), translate_map(Meta, Assocs, TUpdate, US). translate_struct(Meta, Name, {'%{}', MapMeta, Args}, S) -> {Assocs, TUpdate, US} = extract_assoc_update(Args, S), Struct = load_struct(Meta, Name, S), case is_map(Struct) of true -> assert_struct_keys(Meta, Name, Struct, Assocs, S); false -> compile_error(Meta, S#elixir_scope.file, "expected ~ts.__struct__/0 to " "return a map, got: ~ts", [elixir_aliases:inspect(Name), 'Elixir.Kernel':inspect(Struct)]) end, if TUpdate /= nil -> Line = ?line(Meta), {VarName, _, VS} = elixir_scope:build_var('_', US), Var = {var, Line, VarName}, Map = {map, Line, [{map_field_exact, Line, {atom, Line, '__struct__'}, {atom, Line, Name}}]}, Match = {match, Line, Var, Map}, Error = {tuple, Line, [{atom, Line, badstruct}, {atom, Line, Name}, Var]}, {TMap, TS} = translate_map(MapMeta, Assocs, Var, VS), {{'case', Line, TUpdate, [ {clause, Line, [Match], [], [TMap]}, {clause, Line, [Var], [], [elixir_utils:erl_call(Line, erlang, error, [Error])]} ]}, TS}; S#elixir_scope.context == match -> translate_map(MapMeta, Assocs ++ [{'__struct__', Name}], nil, US); true -> Keys = [K || {K, _} <- Assocs], {StructAssocs, _} = elixir_quote:escape(maps:to_list(maps:without(Keys, Struct)), false), translate_map(MapMeta, StructAssocs ++ Assocs ++ [{'__struct__', Name}], nil, US) end. %% Helpers load_struct(Meta, Name, S) -> Context = lists:keyfind(struct, 1, Meta) == {struct, context}, Local = not(ensure_loaded(Name)) andalso (Context orelse wait_for_struct(Name)), try case Local of true -> try (elixir_locals:local_for(Name, '__struct__', 0, def))() catch error:undef -> Name:'__struct__'(); error:badarg -> Name:'__struct__'() end; false -> Name:'__struct__'() end catch error:undef -> Inspected = elixir_aliases:inspect(Name), case Context andalso (S#elixir_scope.function == nil) of true -> compile_error(Meta, S#elixir_scope.file, "cannot access struct ~ts, the struct was not yet defined or the struct is being " "accessed in the same context that defines it", [Inspected]); false -> compile_error(Meta, S#elixir_scope.file, "~ts.__struct__/0 is undefined, " "cannot expand struct ~ts", [Inspected, Inspected]) end end. ensure_loaded(Module) -> case code:ensure_loaded(Module) of {module, Module} -> true; {error, _} -> false end. wait_for_struct(Module) -> case erlang:get(elixir_compiler_pid) of undefined -> false; Pid -> Ref = erlang:make_ref(), Pid ! {waiting, struct, self(), Ref, Module}, receive {Ref, ready} -> true; {Ref, release} -> 'Elixir.Kernel.ErrorHandler':release(), false end end. translate_map(Meta, Assocs, TUpdate, #elixir_scope{extra=Extra} = S) -> {Op, KeyFun, ValFun} = extract_key_val_op(TUpdate, S), Line = ?line(Meta), {TArgs, SA} = lists:mapfoldl(fun({Key, Value}, Acc) -> {TKey, Acc1} = KeyFun(Key, Acc), {TValue, Acc2} = ValFun(Value, Acc1#elixir_scope{extra=Extra}), {{Op, ?line(Meta), TKey, TValue}, Acc2} end, S, Assocs), build_map(Line, TUpdate, TArgs, SA). extract_assoc_update([{'|', _Meta, [Update, Args]}], S) -> {TArg, SA} = elixir_translator:translate_arg(Update, S, S), {Args, TArg, SA}; extract_assoc_update(Args, SA) -> {Args, nil, SA}. extract_key_val_op(_TUpdate, #elixir_scope{context=match}) -> {map_field_exact, fun(X, Acc) -> elixir_translator:translate(X, Acc#elixir_scope{extra=map_key}) end, fun elixir_translator:translate/2}; extract_key_val_op(TUpdate, S) -> KS = S#elixir_scope{extra=map_key}, Op = if TUpdate == nil -> map_field_assoc; true -> map_field_exact end, {Op, fun(X, Acc) -> elixir_translator:translate_arg(X, Acc, KS) end, fun(X, Acc) -> elixir_translator:translate_arg(X, Acc, S) end}. build_map(Line, nil, TArgs, SA) -> {{map, Line, TArgs}, SA}; build_map(Line, TUpdate, TArgs, SA) -> {{map, Line, TUpdate, TArgs}, SA}. assert_struct_keys(Meta, Name, Struct, Assocs, S) -> [begin compile_error(Meta, S#elixir_scope.file, "unknown key ~ts for struct ~ts", ['Elixir.Kernel':inspect(Key), elixir_aliases:inspect(Name)]) end || {Key, _} <- Assocs, not maps:is_key(Key, Struct)]. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_module.erl000066400000000000000000000432061254730255300233200ustar00rootroot00000000000000-module(elixir_module). -export([data_table/1, defs_table/1, clas_table/1, is_open/1, compile/4, expand_callback/6, add_beam_chunk/3, format_error/1]). -include("elixir.hrl"). -define(acc_attr, {elixir, acc_attributes}). -define(lexical_attr, {elixir, lexical_tracker}). -define(persisted_attr, {elixir, persisted_attributes}). -define(overridable_attr, {elixir, overridable}). -define(location_attr, {elixir, location}). %% TABLE METHODS data_table(Module) -> ets:lookup_element(elixir_modules, Module, 2). defs_table(Module) -> ets:lookup_element(elixir_modules, Module, 3). clas_table(Module) -> ets:lookup_element(elixir_modules, Module, 4). is_open(Module) -> ets:lookup(elixir_modules, Module) /= []. %% Compilation hook compile(Module, Block, Vars, #{line := Line} = Env) when is_atom(Module) -> %% In case we are generating a module from inside a function, %% we get rid of the lexical tracker information as, at this %% point, the lexical tracker process is long gone. LexEnv = case ?m(Env, function) of nil -> Env#{module := Module}; _ -> Env#{lexical_tracker := nil, function := nil, module := Module} end, case ?m(LexEnv, lexical_tracker) of nil -> elixir_lexical:run(?m(LexEnv, file), nil, fun(Pid) -> do_compile(Line, Module, Block, Vars, LexEnv#{lexical_tracker := Pid}) end); _ -> do_compile(Line, Module, Block, Vars, LexEnv) end; compile(Module, _Block, _Vars, #{line := Line, file := File}) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {invalid_module, Module}). do_compile(Line, Module, Block, Vars, E) -> File = ?m(E, file), check_module_availability(Line, File, Module), Docs = elixir_compiler:get_opt(docs), {Data, Defs, Clas, Ref} = build(Line, File, Module, Docs, ?m(E, lexical_tracker)), try {Result, NE} = eval_form(Line, Module, Data, Block, Vars, E), _ = case ets:lookup(Data, 'on_load') of [] -> ok; [{on_load, OnLoad}] -> [elixir_locals:record_local(Tuple, Module) || Tuple <- OnLoad] end, {Def, Defp, Defmacro, Defmacrop, Exports, Functions, Unreachable} = elixir_def:unwrap_definitions(File, Module), {All, Forms0} = functions_form(Line, File, Module, Def, Defp, Defmacro, Defmacrop, Exports, Functions), Forms1 = specs_form(Data, Defmacro, Defmacrop, Unreachable, Forms0), Forms2 = types_form(Line, File, Data, Forms1), Forms3 = attributes_form(Line, File, Data, Forms2), elixir_locals:ensure_no_import_conflict(Line, File, Module, All), case Docs of true -> warn_unused_docs(Line, File, Data, doc); false -> false end, Location = {elixir_utils:characters_to_list(elixir_utils:relative_to_cwd(File)), Line}, Final = [ {attribute, Line, file, Location}, {attribute, Line, module, Module} | Forms3 ], Binary = load_form(Line, Data, Final, compile_opts(Module), NE), {module, Module, Binary, Result} catch error:undef -> case erlang:get_stacktrace() of [{Module, Fun, Args, _Info} | _] = Stack when is_list(Args) -> compile_undef(Module, Fun, length(Args), Stack); [{Module, Fun, Arity, _Info} | _] = Stack -> compile_undef(Module, Fun, Arity, Stack); Stack -> erlang:raise(error, undef, Stack) end after elixir_locals:cleanup(Module), ets:delete(Data), ets:delete(Defs), ets:delete(Clas), elixir_code_server:call({undefmodule, Ref}) end. %% An undef error for a function in the module being compiled might result in an %% exception message suggesting the current module is not loaded. This is %% misleading so use a custom reason. compile_undef(Module, Fun, Arity, Stack) -> ExMod = 'Elixir.UndefinedFunctionError', case code:is_loaded(ExMod) of false -> erlang:raise(error, undef, Stack); _ -> Opts = [{module, Module}, {function, Fun}, {arity, Arity}, {reason, 'function not available'}], Exception = 'Elixir.UndefinedFunctionError':exception(Opts), erlang:raise(error, Exception, Stack) end. %% Hook that builds both attribute and functions and set up common hooks. build(Line, File, Module, Docs, Lexical) -> case ets:lookup(elixir_modules, Module) of [{Module, _, _, _, OldLine, OldFile}] -> Error = {module_in_definition, Module, OldFile, OldLine}, elixir_errors:form_error([{line, Line}], File, ?MODULE, Error); _ -> [] end, Data = ets:new(Module, [set, public]), Defs = ets:new(Module, [set, public]), Clas = ets:new(Module, [bag, public]), Ref = elixir_code_server:call({defmodule, self(), {Module, Data, Defs, Clas, Line, File}}), ets:insert(Data, {before_compile, []}), ets:insert(Data, {after_compile, []}), ets:insert(Data, {moduledoc, nil}), ets:insert(Data, {behaviour_docs, []}), OnDefinition = case Docs of true -> [{'Elixir.Module', compile_doc}]; _ -> [] end, ets:insert(Data, {on_definition, OnDefinition}), Attributes = [behaviour, on_load, compile, external_resource, dialyzer], ets:insert(Data, {?acc_attr, [before_compile, after_compile, on_definition, derive, spec, type, typep, opaque, callback|Attributes]}), ets:insert(Data, {?persisted_attr, [vsn|Attributes]}), ets:insert(Data, {?lexical_attr, Lexical}), %% Setup definition related modules elixir_def:setup(Module), elixir_locals:setup(Module), elixir_def_overridable:setup(Module), {Data, Defs, Clas, Ref}. %% Receives the module representation and evaluates it. eval_form(Line, Module, Data, Block, Vars, E) -> {Value, EE} = elixir_compiler:eval_forms(Block, Vars, E), elixir_def_overridable:store_pending(Module), EV = elixir_env:linify({Line, EE#{vars := [], export_vars := nil}}), EC = eval_callbacks(Line, Data, before_compile, [EV], EV), elixir_def_overridable:store_pending(Module), {Value, EC}. eval_callbacks(Line, Data, Name, Args, E) -> Callbacks = lists:reverse(ets:lookup_element(Data, Name, 2)), lists:foldl(fun({M, F}, Acc) -> expand_callback(Line, M, F, Args, Acc#{vars := [], export_vars := nil}, fun(AM, AF, AA) -> apply(AM, AF, AA) end) end, E, Callbacks). %% Return the form with exports and function declarations. functions_form(Line, File, Module, Def, Defp, Defmacro, Defmacrop, Exports, Body) -> All = Def ++ Defmacro ++ Defp ++ Defmacrop, {Spec, Info} = add_info_function(Line, File, Module, All, Def, Defmacro), {[{'__info__', 1}|All], [{attribute, Line, export, lists:sort([{'__info__', 1}|Exports])}, Spec, Info | Body]}. %% Add attributes handling to the form attributes_form(Line, File, Data, Current) -> AccAttrs = ets:lookup_element(Data, ?acc_attr, 2), PersistedAttrs = ets:lookup_element(Data, ?persisted_attr, 2), Transform = fun({Key, Value}, Acc) when is_atom(Key) -> case lists:member(Key, PersistedAttrs) of false -> Acc; true -> Values = case lists:member(Key, AccAttrs) of true -> Value; false -> [Value] end, lists:foldl(fun(X, Final) -> [{attribute, Line, Key, X}|Final] end, Acc, process_attribute(Line, File, Key, Values)) end end, Results = ets:select(Data, [{{'$1', '_'}, [{is_atom, '$1'}], ['$_']}]), lists:foldl(Transform, Current, Results). process_attribute(Line, File, external_resource, Values) -> lists:usort([process_external_resource(Line, File, Value) || Value <- Values]); process_attribute(_Line, _File, _Key, Values) -> Values. process_external_resource(_Line, _File, Value) when is_binary(Value) -> Value; process_external_resource(Line, File, Value) -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {invalid_external_resource, Value}). %% Types types_form(Line, File, Data, Forms0) -> case elixir_compiler:get_opt(internal) of false -> Types0 = get_typespec(Data, type) ++ get_typespec(Data, typep) ++ get_typespec(Data, opaque), Types1 = ['Elixir.Kernel.Typespec':translate_type(Kind, Expr, Doc, Caller) || {Kind, Expr, Doc, Caller} <- Types0], warn_unused_docs(Line, File, Data, typedoc), Forms1 = types_attributes(Types1, Forms0), Forms2 = export_types_attributes(Types1, Forms1), typedocs_attributes(Types1, Forms2); true -> Forms0 end. types_attributes(Types, Forms) -> Fun = fun({{Kind, _NameArity, Expr}, Line, _Export, _Doc}, Acc) -> [{attribute, Line, Kind, Expr}|Acc] end, lists:foldl(Fun, Forms, Types). export_types_attributes(Types, Forms) -> Fun = fun ({{_Kind, NameArity, _Expr}, Line, true, _Doc}, Acc) -> [{attribute, Line, export_type, [NameArity]}|Acc]; ({_Type, _Line, false, _Doc}, Acc) -> Acc end, lists:foldl(Fun, Forms, Types). typedocs_attributes(Types, Forms) -> Fun = fun ({{_Kind, NameArity, _Expr}, Line, true, Doc}, Acc) when Doc =/= nil -> [{attribute, Line, typedoc, {NameArity, Doc}}|Acc]; ({_Type, _Line, _Export, _Doc}, Acc) -> Acc end, lists:foldl(Fun, Forms, Types). %% Specs specs_form(Data, Defmacro, Defmacrop, Unreachable, Forms) -> case elixir_compiler:get_opt(internal) of false -> Specs0 = get_typespec(Data, spec) ++ get_typespec(Data, callback), Specs1 = ['Elixir.Kernel.Typespec':translate_spec(Kind, Expr, Caller) || {Kind, Expr, Caller} <- Specs0], Specs2 = lists:flatmap(fun(Spec) -> translate_macro_spec(Spec, Defmacro, Defmacrop) end, Specs1), Specs3 = lists:filter(fun({{_Kind, NameArity, _Spec}, _Line}) -> not lists:member(NameArity, Unreachable) end, Specs2), specs_attributes(Forms, Specs3); true -> Forms end. specs_attributes(Forms, Specs) -> Dict = lists:foldl(fun({{Kind, NameArity, Spec}, Line}, Acc) -> dict:append({Kind, NameArity}, {Spec, Line}, Acc) end, dict:new(), Specs), dict:fold(fun({Kind, NameArity}, ExprsLines, Acc) -> {Exprs, Lines} = lists:unzip(ExprsLines), Line = lists:min(Lines), [{attribute, Line, Kind, {NameArity, Exprs}}|Acc] end, Forms, Dict). translate_macro_spec({{spec, NameArity, Spec}, Line}, Defmacro, Defmacrop) -> case lists:member(NameArity, Defmacrop) of true -> []; false -> case lists:member(NameArity, Defmacro) of true -> {Name, Arity} = NameArity, [{{spec, {elixir_utils:macro_name(Name), Arity + 1}, spec_for_macro(Spec)}, Line}]; false -> [{{spec, NameArity, Spec}, Line}] end end; translate_macro_spec({{callback, NameArity, Spec}, Line}, _Defmacro, _Defmacrop) -> [{{callback, NameArity, Spec}, Line}]. spec_for_macro({type, Line, 'fun', [{type, _, product, Args}|T]}) -> NewArgs = [{type, Line, term, []}|Args], {type, Line, 'fun', [{type, Line, product, NewArgs}|T]}; spec_for_macro(Else) -> Else. %% Loads the form into the code server. compile_opts(Module) -> case ets:lookup(data_table(Module), compile) of [{compile, Opts}] when is_list(Opts) -> Opts; [] -> [] end. load_form(Line, Data, Forms, Opts, E) -> elixir_compiler:module(Forms, Opts, E, fun(Module, Binary0) -> Docs = elixir_compiler:get_opt(docs), Binary = add_docs_chunk(Binary0, Data, Line, Docs), eval_callbacks(Line, Data, after_compile, [E, Binary], E), case get(elixir_compiled) of Current when is_list(Current) -> put(elixir_compiled, [{Module, Binary}|Current]), case get(elixir_compiler_pid) of undefined -> ok; PID -> Ref = make_ref(), PID ! {module_available, self(), Ref, ?m(E, file), Module, Binary}, receive {Ref, ack} -> ok end end; _ -> ok end, Binary end). add_docs_chunk(Bin, Data, Line, true) -> ChunkData = term_to_binary({elixir_docs_v1, [ {docs, get_docs(Data)}, {moduledoc, get_moduledoc(Line, Data)}, {behaviour_docs, get_behaviour_docs(Data)} ]}), add_beam_chunk(Bin, "ExDc", ChunkData); add_docs_chunk(Bin, _, _, _) -> Bin. get_docs(Data) -> Match = ets:match(Data, {{doc, '$1'}, '$2', '$3', '$4', '$5'}), lists:usort( [{Tuple, Line, Kind, Sig, Doc} || [Tuple, Line, Kind, Sig, Doc] <- Match, Kind =/= type, Kind =/= opaque]). get_moduledoc(Line, Data) -> {Line, ets:lookup_element(Data, moduledoc, 2)}. get_behaviour_docs(Data) -> lists:usort(ets:lookup_element(Data, behaviour_docs, 2)). get_typespec(Data, Key) -> case ets:lookup(Data, Key) of [{Key, Value}] -> Value; [] -> [] end. check_module_availability(Line, File, Module) -> Reserved = ['Elixir.Any', 'Elixir.BitString', 'Elixir.Function', 'Elixir.PID', 'Elixir.Reference', 'Elixir.Elixir', 'Elixir'], case lists:member(Module, Reserved) of true -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {module_reserved, Module}); false -> ok end, case elixir_compiler:get_opt(ignore_module_conflict) of false -> case code:ensure_loaded(Module) of {module, _} -> elixir_errors:form_warn([{line, Line}], File, ?MODULE, {module_defined, Module}); {error, _} -> ok end; true -> ok end. warn_unused_docs(Line, File, Data, Attribute) -> case ets:member(Data, Attribute) of true -> elixir_errors:form_warn([{line, Line}], File, ?MODULE, {unused_doc, Attribute}); _ -> ok end. % __INFO__ add_info_function(Line, File, Module, All, Def, Defmacro) -> Pair = {'__info__', 1}, case lists:member(Pair, All) of true -> elixir_errors:form_error([{line, Line}], File, ?MODULE, {internal_function_overridden, Pair}); false -> Spec = {attribute, Line, spec, {Pair, [{type, Line, 'fun', [ {type, Line, product, [ {type, Line, union, [ {atom, Line, attributes}, {atom, Line, compile}, {atom, Line, functions}, {atom, Line, macros}, {atom, Line, module} ]} ]}, {type, Line, union, [ {type, Line, atom, []}, {type, Line, list, [ {type, Line, tuple, [ {type, Line, atom, []}, {type, Line, any, []} ]} ]} ]} ]}] }}, Info = {function, 0, '__info__', 1, [ functions_clause(Def), macros_clause(Defmacro), module_clause(Module), info_clause(Module, attributes), info_clause(Module, compile) ]}, {Spec, Info} end. functions_clause(Def) -> {clause, 0, [{atom, 0, functions}], [], [elixir_utils:elixir_to_erl(lists:sort(Def))]}. macros_clause(Defmacro) -> {clause, 0, [{atom, 0, macros}], [], [elixir_utils:elixir_to_erl(lists:sort(Defmacro))]}. module_clause(Module) -> {clause, 0, [{atom, 0, module}], [], [{atom, 0, Module}]}. info_clause(Module, Atom) -> Info = {call, 0, {remote, 0, {atom, 0, erlang}, {atom, 0, get_module_info}}, [{atom, 0, Module}, {atom, 0, Atom}]}, {clause, 0, [{atom, 0, Atom}], [], [Info]}. % HELPERS %% Adds custom chunk to a .beam binary add_beam_chunk(Bin, Id, ChunkData) when is_binary(Bin), is_list(Id), is_binary(ChunkData) -> {ok, _, Chunks0} = beam_lib:all_chunks(Bin), NewChunk = {Id, ChunkData}, Chunks = [NewChunk|Chunks0], {ok, NewBin} = beam_lib:build_module(Chunks), NewBin. %% Expands a callback given by M:F(Args). In case %% the callback can't be expanded, invokes the given %% fun passing a possibly expanded AM:AF(Args). expand_callback(Line, M, F, Args, E, Fun) -> Meta = [{line, Line}, {require, false}], {EE, ET} = elixir_dispatch:dispatch_require(Meta, M, F, Args, E, fun(AM, AF, AA) -> Fun(AM, AF, AA), {ok, E} end), if is_atom(EE) -> ET; true -> try {_Value, _Binding, EF, _S} = elixir:eval_forms(EE, [], ET), EF catch Kind:Reason -> Info = {M, F, length(Args), location(Line, E)}, erlang:raise(Kind, Reason, prune_stacktrace(Info, erlang:get_stacktrace())) end end. location(Line, E) -> [{file, elixir_utils:characters_to_list(?m(E, file))}, {line, Line}]. %% We've reached the elixir_module or eval internals, skip it with the rest prune_stacktrace(Info, [{elixir, eval_forms, _, _}|_]) -> [Info]; prune_stacktrace(Info, [{elixir_module, _, _, _}|_]) -> [Info]; prune_stacktrace(Info, [H|T]) -> [H|prune_stacktrace(Info, T)]; prune_stacktrace(Info, []) -> [Info]. % ERROR HANDLING format_error({invalid_external_resource, Value}) -> io_lib:format("expected a string value for @external_resource, got: ~p", ['Elixir.Kernel':inspect(Value)]); format_error({unused_doc, typedoc}) -> "@typedoc provided but no type follows it"; format_error({unused_doc, doc}) -> "@doc provided but no definition follows it"; format_error({internal_function_overridden, {Name, Arity}}) -> io_lib:format("function ~ts/~B is internal and should not be overridden", [Name, Arity]); format_error({invalid_module, Module}) -> io_lib:format("invalid module name: ~ts", ['Elixir.Kernel':inspect(Module)]); format_error({module_defined, Module}) -> io_lib:format("redefining module ~ts", [elixir_aliases:inspect(Module)]); format_error({module_reserved, Module}) -> io_lib:format("module ~ts is reserved and cannot be defined", [elixir_aliases:inspect(Module)]); format_error({module_in_definition, Module, File, Line}) -> io_lib:format("cannot define module ~ts because it is currently being defined in ~ts:~B", [elixir_aliases:inspect(Module), 'Elixir.Path':relative_to_cwd(File), Line]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_parser.yrl000066400000000000000000000741421254730255300233560ustar00rootroot00000000000000Nonterminals grammar expr_list expr container_expr block_expr access_expr no_parens_expr no_parens_one_expr no_parens_one_ambig_expr bracket_expr bracket_at_expr bracket_arg matched_expr unmatched_expr max_expr unmatched_op_expr matched_op_expr no_parens_op_expr no_parens_many_expr comp_op_eol at_op_eol unary_op_eol and_op_eol or_op_eol capture_op_eol add_op_eol mult_op_eol hat_op_eol two_op_eol pipe_op_eol stab_op_eol arrow_op_eol match_op_eol when_op_eol in_op_eol in_match_op_eol type_op_eol rel_op_eol open_paren close_paren empty_paren eoe list list_args open_bracket close_bracket tuple open_curly close_curly bit_string open_bit close_bit map map_op map_close map_args map_expr struct_op assoc_op_eol assoc_expr assoc_base assoc_update assoc_update_kw assoc container_args_base container_args call_args_parens_expr call_args_parens_base call_args_parens parens_call call_args_no_parens_one call_args_no_parens_ambig call_args_no_parens_expr call_args_no_parens_comma_expr call_args_no_parens_all call_args_no_parens_many call_args_no_parens_many_strict stab stab_eoe stab_expr stab_maybe_expr stab_parens_many kw_eol kw_base kw call_args_no_parens_kw_expr call_args_no_parens_kw dot_op dot_alias dot_identifier dot_op_identifier dot_do_identifier dot_paren_identifier dot_bracket_identifier do_block fn_eoe do_eoe end_eoe block_eoe block_item block_list . Terminals identifier kw_identifier kw_identifier_safe kw_identifier_unsafe bracket_identifier paren_identifier do_identifier block_identifier fn 'end' aliases number signed_number atom atom_safe atom_unsafe bin_string list_string sigil dot_call_op op_identifier comp_op at_op unary_op and_op or_op arrow_op match_op in_op in_match_op type_op dual_op add_op mult_op hat_op two_op pipe_op stab_op when_op assoc_op capture_op rel_op 'true' 'false' 'nil' 'do' eol ';' ',' '.' '(' ')' '[' ']' '{' '}' '<<' '>>' '%{}' '%' . Rootsymbol grammar. %% Two shift/reduce conflicts coming from call_args_parens. Expect 2. %% Changes in ops and precedence should be reflected on lib/elixir/lib/macro.ex %% Note though the operator => in practice has lower precedence than all others, %% its entry in the table is only to support the %{user | foo => bar} syntax. Left 5 do. Right 10 stab_op_eol. %% -> Left 20 ','. Nonassoc 30 capture_op_eol. %% & Left 40 in_match_op_eol. %% <-, \\ (allowed in matches along =) Right 50 when_op_eol. %% when Right 60 type_op_eol. %% :: Right 70 pipe_op_eol. %% | Right 80 assoc_op_eol. %% => Right 90 match_op_eol. %% = Left 130 or_op_eol. %% ||, |||, or Left 140 and_op_eol. %% &&, &&&, and Left 150 comp_op_eol. %% ==, !=, =~, ===, !== Left 160 rel_op_eol. %% <, >, <=, >= Left 170 arrow_op_eol. %% < (op), (op) > (|>, <<<, >>>, ~>>, <<~, ~>, <~, <~>, <|>) Left 180 in_op_eol. %% in Right 200 two_op_eol. %% ++, --, .., <> Left 210 add_op_eol. %% + (op), - (op) Left 220 mult_op_eol. %% * (op), / (op) Left 250 hat_op_eol. %% ^ (op) (^^^) Nonassoc 300 unary_op_eol. %% +, -, !, ^, not, ~~~ Left 310 dot_call_op. Left 310 dot_op. %% . Nonassoc 320 at_op_eol. %% @ Nonassoc 330 dot_identifier. %%% MAIN FLOW OF EXPRESSIONS grammar -> eoe : nil. grammar -> expr_list : to_block('$1'). grammar -> eoe expr_list : to_block('$2'). grammar -> expr_list eoe : to_block('$1'). grammar -> eoe expr_list eoe : to_block('$2'). grammar -> '$empty' : nil. % Note expressions are on reverse order expr_list -> expr : ['$1']. expr_list -> expr_list eoe expr : ['$3'|'$1']. expr -> matched_expr : '$1'. expr -> no_parens_expr : '$1'. expr -> unmatched_expr : '$1'. %% In Elixir we have three main call syntaxes: with parentheses, %% without parentheses and with do blocks. They are represented %% in the AST as matched, no_parens and unmatched. %% %% Calls without parentheses are further divided according to how %% problematic they are: %% %% (a) no_parens_one: a call with one unproblematic argument %% (e.g. `f a` or `f g a` and similar) (includes unary operators) %% %% (b) no_parens_many: a call with several arguments (e.g. `f a, b`) %% %% (c) no_parens_one_ambig: a call with one argument which is %% itself a no_parens_many or no_parens_one_ambig (e.g. `f g a, b` %% or `f g h a, b` and similar) %% %% Note, in particular, that no_parens_one_ambig expressions are %% ambiguous and are interpreted such that the outer function has %% arity 1 (e.g. `f g a, b` is interpreted as `f(g(a, b))` rather %% than `f(g(a), b)`). Hence the name, no_parens_one_ambig. %% %% The distinction is required because we can't, for example, have %% a function call with a do block as argument inside another do %% block call, unless there are parentheses: %% %% if if true do true else false end do #=> invalid %% if(if true do true else false end) do #=> valid %% %% Similarly, it is not possible to nest calls without parentheses %% if their arity is more than 1: %% %% foo a, bar b, c #=> invalid %% foo(a, bar b, c) #=> invalid %% foo bar a, b #=> valid %% foo a, bar(b, c) #=> valid %% %% So the different grammar rules need to take into account %% if calls without parentheses are do blocks in particular %% segments and act accordingly. matched_expr -> matched_expr matched_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). matched_expr -> unary_op_eol matched_expr : build_unary_op('$1', '$2'). matched_expr -> at_op_eol matched_expr : build_unary_op('$1', '$2'). matched_expr -> capture_op_eol matched_expr : build_unary_op('$1', '$2'). matched_expr -> no_parens_one_expr : '$1'. matched_expr -> access_expr : '$1'. unmatched_expr -> matched_expr unmatched_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). unmatched_expr -> unmatched_expr matched_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). unmatched_expr -> unmatched_expr unmatched_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). unmatched_expr -> unmatched_expr no_parens_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). unmatched_expr -> unary_op_eol expr : build_unary_op('$1', '$2'). unmatched_expr -> at_op_eol expr : build_unary_op('$1', '$2'). unmatched_expr -> capture_op_eol expr : build_unary_op('$1', '$2'). unmatched_expr -> block_expr : '$1'. no_parens_expr -> matched_expr no_parens_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')). no_parens_expr -> unary_op_eol no_parens_expr : build_unary_op('$1', '$2'). no_parens_expr -> at_op_eol no_parens_expr : build_unary_op('$1', '$2'). no_parens_expr -> capture_op_eol no_parens_expr : build_unary_op('$1', '$2'). no_parens_expr -> no_parens_one_ambig_expr : '$1'. no_parens_expr -> no_parens_many_expr : '$1'. block_expr -> parens_call call_args_parens do_block : build_identifier('$1', '$2' ++ '$3'). block_expr -> parens_call call_args_parens call_args_parens do_block : build_nested_parens('$1', '$2', '$3' ++ '$4'). block_expr -> dot_do_identifier do_block : build_identifier('$1', '$2'). block_expr -> dot_identifier call_args_no_parens_all do_block : build_identifier('$1', '$2' ++ '$3'). matched_op_expr -> match_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> add_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> mult_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> hat_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> two_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> and_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> or_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> in_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> in_match_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> type_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> when_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> pipe_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> comp_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> rel_op_eol matched_expr : {'$1', '$2'}. matched_op_expr -> arrow_op_eol matched_expr : {'$1', '$2'}. unmatched_op_expr -> match_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> add_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> mult_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> hat_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> two_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> and_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> or_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> in_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> in_match_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> type_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> when_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> pipe_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> comp_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> rel_op_eol unmatched_expr : {'$1', '$2'}. unmatched_op_expr -> arrow_op_eol unmatched_expr : {'$1', '$2'}. no_parens_op_expr -> match_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> add_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> mult_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> hat_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> two_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> and_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> or_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> in_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> in_match_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> type_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> when_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> pipe_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> comp_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> rel_op_eol no_parens_expr : {'$1', '$2'}. no_parens_op_expr -> arrow_op_eol no_parens_expr : {'$1', '$2'}. %% Allow when (and only when) with keywords no_parens_op_expr -> when_op_eol call_args_no_parens_kw : {'$1', '$2'}. no_parens_one_ambig_expr -> dot_op_identifier call_args_no_parens_ambig : build_identifier('$1', '$2'). no_parens_one_ambig_expr -> dot_identifier call_args_no_parens_ambig : build_identifier('$1', '$2'). no_parens_many_expr -> dot_op_identifier call_args_no_parens_many_strict : build_identifier('$1', '$2'). no_parens_many_expr -> dot_identifier call_args_no_parens_many_strict : build_identifier('$1', '$2'). no_parens_one_expr -> dot_op_identifier call_args_no_parens_one : build_identifier('$1', '$2'). no_parens_one_expr -> dot_identifier call_args_no_parens_one : build_identifier('$1', '$2'). no_parens_one_expr -> dot_do_identifier : build_identifier('$1', nil). no_parens_one_expr -> dot_identifier : build_identifier('$1', nil). %% From this point on, we just have constructs that can be %% used with the access syntax. Notice that (dot_)identifier %% is not included in this list simply because the tokenizer %% marks identifiers followed by brackets as bracket_identifier. access_expr -> bracket_at_expr : '$1'. access_expr -> bracket_expr : '$1'. access_expr -> at_op_eol number : build_unary_op('$1', ?exprs('$2')). access_expr -> unary_op_eol number : build_unary_op('$1', ?exprs('$2')). access_expr -> capture_op_eol number : build_unary_op('$1', ?exprs('$2')). access_expr -> fn_eoe stab end_eoe : build_fn('$1', build_stab(reverse('$2'))). access_expr -> open_paren stab close_paren : build_stab(reverse('$2')). access_expr -> open_paren stab ';' close_paren : build_stab(reverse('$2')). access_expr -> open_paren ';' stab ';' close_paren : build_stab(reverse('$3')). access_expr -> open_paren ';' stab close_paren : build_stab(reverse('$3')). access_expr -> open_paren ';' close_paren : build_stab([]). access_expr -> empty_paren : nil. access_expr -> number : ?exprs('$1'). access_expr -> signed_number : {element(4, '$1'), meta('$1'), ?exprs('$1')}. access_expr -> list : element(1, '$1'). access_expr -> map : '$1'. access_expr -> tuple : '$1'. access_expr -> 'true' : ?id('$1'). access_expr -> 'false' : ?id('$1'). access_expr -> 'nil' : ?id('$1'). access_expr -> bin_string : build_bin_string('$1'). access_expr -> list_string : build_list_string('$1'). access_expr -> bit_string : '$1'. access_expr -> sigil : build_sigil('$1'). access_expr -> max_expr : '$1'. %% Aliases and properly formed calls. Used by map_expr. max_expr -> atom : ?exprs('$1'). max_expr -> atom_safe : build_quoted_atom('$1', true). max_expr -> atom_unsafe : build_quoted_atom('$1', false). max_expr -> parens_call call_args_parens : build_identifier('$1', '$2'). max_expr -> parens_call call_args_parens call_args_parens : build_nested_parens('$1', '$2', '$3'). max_expr -> dot_alias : '$1'. bracket_arg -> open_bracket kw close_bracket : build_list('$1', '$2'). bracket_arg -> open_bracket container_expr close_bracket : build_list('$1', '$2'). bracket_arg -> open_bracket container_expr ',' close_bracket : build_list('$1', '$2'). bracket_expr -> dot_bracket_identifier bracket_arg : build_access(build_identifier('$1', nil), '$2'). bracket_expr -> access_expr bracket_arg : build_access('$1', '$2'). bracket_at_expr -> at_op_eol dot_bracket_identifier bracket_arg : build_access(build_unary_op('$1', build_identifier('$2', nil)), '$3'). bracket_at_expr -> at_op_eol access_expr bracket_arg : build_access(build_unary_op('$1', '$2'), '$3'). %% Blocks do_block -> do_eoe 'end' : [[{do, nil}]]. do_block -> do_eoe stab end_eoe : [[{do, build_stab(reverse('$2'))}]]. do_block -> do_eoe block_list 'end' : [[{do, nil}|'$2']]. do_block -> do_eoe stab_eoe block_list 'end' : [[{do, build_stab(reverse('$2'))}|'$3']]. eoe -> eol : '$1'. eoe -> ';' : '$1'. eoe -> eol ';' : '$1'. fn_eoe -> 'fn' : '$1'. fn_eoe -> 'fn' eoe : '$1'. do_eoe -> 'do' : '$1'. do_eoe -> 'do' eoe : '$1'. end_eoe -> 'end' : '$1'. end_eoe -> eoe 'end' : '$2'. block_eoe -> block_identifier : '$1'. block_eoe -> block_identifier eoe : '$1'. stab -> stab_expr : ['$1']. stab -> stab eoe stab_expr : ['$3'|'$1']. stab_eoe -> stab : '$1'. stab_eoe -> stab eoe : '$1'. stab_expr -> expr : '$1'. stab_expr -> stab_op_eol stab_maybe_expr : build_op('$1', [], '$2'). stab_expr -> empty_paren stab_op_eol stab_maybe_expr : build_op('$2', [], '$3'). stab_expr -> call_args_no_parens_all stab_op_eol stab_maybe_expr : build_op('$2', unwrap_when(unwrap_splice('$1')), '$3'). stab_expr -> stab_parens_many stab_op_eol stab_maybe_expr : build_op('$2', unwrap_splice('$1'), '$3'). stab_expr -> stab_parens_many when_op expr stab_op_eol stab_maybe_expr : build_op('$4', [{'when', meta('$2'), unwrap_splice('$1') ++ ['$3']}], '$5'). stab_maybe_expr -> 'expr' : '$1'. stab_maybe_expr -> '$empty' : nil. block_item -> block_eoe stab_eoe : {?exprs('$1'), build_stab(reverse('$2'))}. block_item -> block_eoe : {?exprs('$1'), nil}. block_list -> block_item : ['$1']. block_list -> block_item block_list : ['$1'|'$2']. %% Helpers open_paren -> '(' : '$1'. open_paren -> '(' eol : '$1'. close_paren -> ')' : '$1'. close_paren -> eol ')' : '$2'. empty_paren -> open_paren ')' : '$1'. open_bracket -> '[' : '$1'. open_bracket -> '[' eol : '$1'. close_bracket -> ']' : '$1'. close_bracket -> eol ']' : '$2'. open_bit -> '<<' : '$1'. open_bit -> '<<' eol : '$1'. close_bit -> '>>' : '$1'. close_bit -> eol '>>' : '$2'. open_curly -> '{' : '$1'. open_curly -> '{' eol : '$1'. close_curly -> '}' : '$1'. close_curly -> eol '}' : '$2'. % Operators add_op_eol -> add_op : '$1'. add_op_eol -> add_op eol : '$1'. add_op_eol -> dual_op : '$1'. add_op_eol -> dual_op eol : '$1'. mult_op_eol -> mult_op : '$1'. mult_op_eol -> mult_op eol : '$1'. hat_op_eol -> hat_op : '$1'. hat_op_eol -> hat_op eol : '$1'. two_op_eol -> two_op : '$1'. two_op_eol -> two_op eol : '$1'. pipe_op_eol -> pipe_op : '$1'. pipe_op_eol -> pipe_op eol : '$1'. capture_op_eol -> capture_op : '$1'. capture_op_eol -> capture_op eol : '$1'. unary_op_eol -> unary_op : '$1'. unary_op_eol -> unary_op eol : '$1'. unary_op_eol -> dual_op : '$1'. unary_op_eol -> dual_op eol : '$1'. match_op_eol -> match_op : '$1'. match_op_eol -> match_op eol : '$1'. and_op_eol -> and_op : '$1'. and_op_eol -> and_op eol : '$1'. or_op_eol -> or_op : '$1'. or_op_eol -> or_op eol : '$1'. in_op_eol -> in_op : '$1'. in_op_eol -> in_op eol : '$1'. in_match_op_eol -> in_match_op : '$1'. in_match_op_eol -> in_match_op eol : '$1'. type_op_eol -> type_op : '$1'. type_op_eol -> type_op eol : '$1'. when_op_eol -> when_op : '$1'. when_op_eol -> when_op eol : '$1'. stab_op_eol -> stab_op : '$1'. stab_op_eol -> stab_op eol : '$1'. at_op_eol -> at_op : '$1'. at_op_eol -> at_op eol : '$1'. comp_op_eol -> comp_op : '$1'. comp_op_eol -> comp_op eol : '$1'. rel_op_eol -> rel_op : '$1'. rel_op_eol -> rel_op eol : '$1'. arrow_op_eol -> arrow_op : '$1'. arrow_op_eol -> arrow_op eol : '$1'. % Dot operator dot_op -> '.' : '$1'. dot_op -> '.' eol : '$1'. dot_identifier -> identifier : '$1'. dot_identifier -> matched_expr dot_op identifier : build_dot('$2', '$1', '$3'). dot_alias -> aliases : {'__aliases__', meta('$1', 0), ?exprs('$1')}. dot_alias -> matched_expr dot_op aliases : build_dot_alias('$2', '$1', '$3'). dot_op_identifier -> op_identifier : '$1'. dot_op_identifier -> matched_expr dot_op op_identifier : build_dot('$2', '$1', '$3'). dot_do_identifier -> do_identifier : '$1'. dot_do_identifier -> matched_expr dot_op do_identifier : build_dot('$2', '$1', '$3'). dot_bracket_identifier -> bracket_identifier : '$1'. dot_bracket_identifier -> matched_expr dot_op bracket_identifier : build_dot('$2', '$1', '$3'). dot_paren_identifier -> paren_identifier : '$1'. dot_paren_identifier -> matched_expr dot_op paren_identifier : build_dot('$2', '$1', '$3'). parens_call -> dot_paren_identifier : '$1'. parens_call -> matched_expr dot_call_op : {'.', meta('$2'), ['$1']}. % Fun/local calls % Function calls with no parentheses call_args_no_parens_expr -> matched_expr : '$1'. call_args_no_parens_expr -> no_parens_expr : throw_no_parens_many_strict('$1'). call_args_no_parens_comma_expr -> matched_expr ',' call_args_no_parens_expr : ['$3', '$1']. call_args_no_parens_comma_expr -> call_args_no_parens_comma_expr ',' call_args_no_parens_expr : ['$3'|'$1']. call_args_no_parens_all -> call_args_no_parens_one : '$1'. call_args_no_parens_all -> call_args_no_parens_ambig : '$1'. call_args_no_parens_all -> call_args_no_parens_many : '$1'. call_args_no_parens_one -> call_args_no_parens_kw : ['$1']. call_args_no_parens_one -> matched_expr : ['$1']. call_args_no_parens_ambig -> no_parens_expr : ['$1']. call_args_no_parens_many -> matched_expr ',' call_args_no_parens_kw : ['$1', '$3']. call_args_no_parens_many -> call_args_no_parens_comma_expr : reverse('$1'). call_args_no_parens_many -> call_args_no_parens_comma_expr ',' call_args_no_parens_kw : reverse(['$3'|'$1']). call_args_no_parens_many_strict -> call_args_no_parens_many : '$1'. call_args_no_parens_many_strict -> open_paren call_args_no_parens_kw close_paren : throw_no_parens_strict('$1'). call_args_no_parens_many_strict -> open_paren call_args_no_parens_many close_paren : throw_no_parens_strict('$1'). stab_parens_many -> open_paren call_args_no_parens_kw close_paren : ['$2']. stab_parens_many -> open_paren call_args_no_parens_many close_paren : '$2'. % Containers container_expr -> matched_expr : '$1'. container_expr -> unmatched_expr : '$1'. container_expr -> no_parens_expr : throw_no_parens_many_strict('$1'). container_args_base -> container_expr : ['$1']. container_args_base -> container_args_base ',' container_expr : ['$3'|'$1']. container_args -> container_args_base : lists:reverse('$1'). container_args -> container_args_base ',' : lists:reverse('$1'). container_args -> container_args_base ',' kw : lists:reverse(['$3'|'$1']). % Function calls with parentheses call_args_parens_expr -> matched_expr : '$1'. call_args_parens_expr -> unmatched_expr : '$1'. call_args_parens_expr -> no_parens_expr : throw_no_parens_many_strict('$1'). call_args_parens_base -> call_args_parens_expr : ['$1']. call_args_parens_base -> call_args_parens_base ',' call_args_parens_expr : ['$3'|'$1']. call_args_parens -> empty_paren : []. call_args_parens -> open_paren no_parens_expr close_paren : ['$2']. call_args_parens -> open_paren kw close_paren : ['$2']. call_args_parens -> open_paren call_args_parens_base close_paren : reverse('$2'). call_args_parens -> open_paren call_args_parens_base ',' kw close_paren : reverse(['$4'|'$2']). % KV kw_eol -> kw_identifier : ?exprs('$1'). kw_eol -> kw_identifier eol : ?exprs('$1'). kw_eol -> kw_identifier_safe : build_quoted_atom('$1', true). kw_eol -> kw_identifier_safe eol : build_quoted_atom('$1', true). kw_eol -> kw_identifier_unsafe : build_quoted_atom('$1', false). kw_eol -> kw_identifier_unsafe eol : build_quoted_atom('$1', false). kw_base -> kw_eol container_expr : [{'$1', '$2'}]. kw_base -> kw_base ',' kw_eol container_expr : [{'$3', '$4'}|'$1']. kw -> kw_base : reverse('$1'). kw -> kw_base ',' : reverse('$1'). call_args_no_parens_kw_expr -> kw_eol matched_expr : {'$1', '$2'}. call_args_no_parens_kw_expr -> kw_eol no_parens_expr : {'$1', '$2'}. call_args_no_parens_kw -> call_args_no_parens_kw_expr : ['$1']. call_args_no_parens_kw -> call_args_no_parens_kw_expr ',' call_args_no_parens_kw : ['$1'|'$3']. % Lists list_args -> kw : '$1'. list_args -> container_args_base : reverse('$1'). list_args -> container_args_base ',' : reverse('$1'). list_args -> container_args_base ',' kw : reverse('$1', '$3'). list -> open_bracket ']' : build_list('$1', []). list -> open_bracket list_args close_bracket : build_list('$1', '$2'). % Tuple tuple -> open_curly '}' : build_tuple('$1', []). tuple -> open_curly container_args close_curly : build_tuple('$1', '$2'). % Bitstrings bit_string -> open_bit '>>' : build_bit('$1', []). bit_string -> open_bit container_args close_bit : build_bit('$1', '$2'). % Map and structs %% Allow unquote/@something/aliases inside maps and structs. map_expr -> max_expr : '$1'. map_expr -> dot_identifier : build_identifier('$1', nil). map_expr -> at_op_eol map_expr : build_unary_op('$1', '$2'). assoc_op_eol -> assoc_op : '$1'. assoc_op_eol -> assoc_op eol : '$1'. assoc_expr -> matched_expr assoc_op_eol matched_expr : {'$1', '$3'}. assoc_expr -> unmatched_expr assoc_op_eol unmatched_expr : {'$1', '$3'}. assoc_expr -> matched_expr assoc_op_eol unmatched_expr : {'$1', '$3'}. assoc_expr -> unmatched_expr assoc_op_eol matched_expr : {'$1', '$3'}. assoc_expr -> map_expr : '$1'. assoc_update -> matched_expr pipe_op_eol assoc_expr : {'$2', '$1', ['$3']}. assoc_update -> unmatched_expr pipe_op_eol assoc_expr : {'$2', '$1', ['$3']}. assoc_update_kw -> matched_expr pipe_op_eol kw : {'$2', '$1', '$3'}. assoc_update_kw -> unmatched_expr pipe_op_eol kw : {'$2', '$1', '$3'}. assoc_base -> assoc_expr : ['$1']. assoc_base -> assoc_base ',' assoc_expr : ['$3'|'$1']. assoc -> assoc_base : reverse('$1'). assoc -> assoc_base ',' : reverse('$1'). map_op -> '%{}' : '$1'. map_op -> '%{}' eol : '$1'. map_close -> kw close_curly : '$1'. map_close -> assoc close_curly : '$1'. map_close -> assoc_base ',' kw close_curly : reverse('$1', '$3'). map_args -> open_curly '}' : build_map('$1', []). map_args -> open_curly map_close : build_map('$1', '$2'). map_args -> open_curly assoc_update close_curly : build_map_update('$1', '$2', []). map_args -> open_curly assoc_update ',' close_curly : build_map_update('$1', '$2', []). map_args -> open_curly assoc_update ',' map_close : build_map_update('$1', '$2', '$4'). map_args -> open_curly assoc_update_kw close_curly : build_map_update('$1', '$2', []). struct_op -> '%' : '$1'. struct_op -> '%' eol : '$1'. map -> map_op map_args : '$2'. map -> struct_op map_expr map_args : {'%', meta('$1'), ['$2', '$3']}. map -> struct_op map_expr eol map_args : {'%', meta('$1'), ['$2', '$4']}. Erlang code. -define(id(Node), element(1, Node)). -define(line(Node), element(2, Node)). -define(exprs(Node), element(3, Node)). -define(rearrange_uop(Op), (Op == 'not' orelse Op == '!')). %% The following directive is needed for (significantly) faster %% compilation of the generated .erl file by the HiPE compiler -compile([{hipe, [{regalloc, linear_scan}]}]). -import(lists, [reverse/1, reverse/2]). meta(Line, Counter) -> [{counter, Counter}|meta(Line)]. meta({Line, Column, EndColumn}) when is_integer(Line), is_integer(Column), is_integer(EndColumn) -> [{line, Line}]; meta(Node) -> meta(?line(Node)). %% Operators build_op({_Kind, Line, 'in'}, {UOp, _, [Left]}, Right) when ?rearrange_uop(UOp) -> {UOp, meta(Line), [{'in', meta(Line), [Left, Right]}]}; build_op({_Kind, Line, Op}, Left, Right) -> {Op, meta(Line), [Left, Right]}. build_unary_op({_Kind, Line, Op}, Expr) -> {Op, meta(Line), [Expr]}. build_list(Marker, Args) -> {Args, ?line(Marker)}. build_tuple(_Marker, [Left, Right]) -> {Left, Right}; build_tuple(Marker, Args) -> {'{}', meta(Marker), Args}. build_bit(Marker, Args) -> {'<<>>', meta(Marker), Args}. build_map(Marker, Args) -> {'%{}', meta(Marker), Args}. build_map_update(Marker, {Pipe, Left, Right}, Extra) -> {'%{}', meta(Marker), [build_op(Pipe, Left, Right ++ Extra)]}. %% Blocks build_block([{Op, _, [_]}]=Exprs) when ?rearrange_uop(Op) -> {'__block__', [], Exprs}; build_block([{unquote_splicing, _, Args}]=Exprs) when length(Args) =< 2 -> {'__block__', [], Exprs}; build_block([Expr]) -> Expr; build_block(Exprs) -> {'__block__', [], Exprs}. %% Dots build_dot_alias(Dot, {'__aliases__', _, Left}, {'aliases', _, Right}) -> {'__aliases__', meta(Dot), Left ++ Right}; build_dot_alias(_Dot, Atom, {'aliases', {Line, _, _}, _}) when is_atom(Atom) -> throw_bad_atom(Line); build_dot_alias(Dot, Other, {'aliases', _, Right}) -> {'__aliases__', meta(Dot), [Other|Right]}. build_dot(Dot, Left, Right) -> {'.', meta(Dot), [Left, extract_identifier(Right)]}. extract_identifier({Kind, _, Identifier}) when Kind == identifier; Kind == bracket_identifier; Kind == paren_identifier; Kind == do_identifier; Kind == op_identifier -> Identifier. %% Identifiers build_nested_parens(Dot, Args1, Args2) -> Identifier = build_identifier(Dot, Args1), Meta = element(2, Identifier), {Identifier, Meta, Args2}. build_identifier({'.', Meta, _} = Dot, Args) -> FArgs = case Args of nil -> []; _ -> Args end, {Dot, Meta, FArgs}; build_identifier({Keyword, Line}, Args) when Keyword == fn -> {fn, meta(Line), Args}; build_identifier({op_identifier, Line, Identifier}, [Arg]) -> {Identifier, [{ambiguous_op, nil}|meta(Line)], [Arg]}; build_identifier({_, Line, Identifier}, Args) -> {Identifier, meta(Line), Args}. %% Fn build_fn(Op, Stab) -> {fn, meta(Op), Stab}. %% Access build_access(Expr, {List, Line}) -> Meta = meta(Line), {{'.', Meta, ['Elixir.Access', get]}, Meta, [Expr, List]}. %% Interpolation aware build_sigil({sigil, Line, Sigil, Parts, Modifiers}) -> Meta = meta(Line), {list_to_atom("sigil_" ++ [Sigil]), Meta, [ {'<<>>', Meta, string_parts(Parts)}, Modifiers ]}. build_bin_string({bin_string, _Line, [H]}) when is_binary(H) -> H; build_bin_string({bin_string, Line, Args}) -> {'<<>>', meta(Line), string_parts(Args)}. build_list_string({list_string, _Line, [H]}) when is_binary(H) -> elixir_utils:characters_to_list(H); build_list_string({list_string, Line, Args}) -> Meta = meta(Line), {{'.', Meta, ['Elixir.String', to_char_list]}, Meta, [{'<<>>', Meta, string_parts(Args)}]}. build_quoted_atom({_, _Line, [H]}, Safe) when is_binary(H) -> Op = binary_to_atom_op(Safe), erlang:Op(H, utf8); build_quoted_atom({_, Line, Args}, Safe) -> Meta = meta(Line), {{'.', Meta, [erlang, binary_to_atom_op(Safe)]}, Meta, [{'<<>>', Meta, string_parts(Args)}, utf8]}. binary_to_atom_op(true) -> binary_to_existing_atom; binary_to_atom_op(false) -> binary_to_atom. string_parts(Parts) -> [string_part(Part) || Part <- Parts]. string_part(Binary) when is_binary(Binary) -> Binary; string_part({Line, Tokens}) -> Form = string_tokens_parse(Tokens), Meta = meta(Line), {'::', Meta, [{{'.', Meta, ['Elixir.Kernel', to_string]}, Meta, [Form]}, {binary, Meta, nil}]}. string_tokens_parse(Tokens) -> case parse(Tokens) of {ok, Forms} -> Forms; {error, _} = Error -> throw(Error) end. %% Keywords build_stab([{'->', Meta, [Left, Right]}|T]) -> build_stab(Meta, T, Left, [Right], []); build_stab(Else) -> build_block(Else). build_stab(Old, [{'->', New, [Left, Right]}|T], Marker, Temp, Acc) -> H = {'->', Old, [Marker, build_block(reverse(Temp))]}, build_stab(New, T, Left, [Right], [H|Acc]); build_stab(Meta, [H|T], Marker, Temp, Acc) -> build_stab(Meta, T, Marker, [H|Temp], Acc); build_stab(Meta, [], Marker, Temp, Acc) -> H = {'->', Meta, [Marker, build_block(reverse(Temp))]}, reverse([H|Acc]). %% Every time the parser sees a (unquote_splicing()) %% it assumes that a block is being spliced, wrapping %% the splicing in a __block__. But in the stab clause, %% we can have (unquote_splicing(1, 2, 3)) -> :ok, in such %% case, we don't actually want the block, since it is %% an arg style call. unwrap_splice unwraps the splice %% from such blocks. unwrap_splice([{'__block__', [], [{unquote_splicing, _, _}] = Splice}]) -> Splice; unwrap_splice(Other) -> Other. unwrap_when(Args) -> case elixir_utils:split_last(Args) of {Start, {'when', Meta, [_, _] = End}} -> [{'when', Meta, Start ++ End}]; {_, _} -> Args end. to_block([One]) -> One; to_block(Other) -> {'__block__', [], reverse(Other)}. %% Errors throw(Line, Error, Token) -> throw({error, {Line, ?MODULE, [Error, Token]}}). throw_no_parens_strict(Token) -> throw(?line(Token), "unexpected parentheses. If you are making a " "function call, do not insert spaces between the function name and the " "opening parentheses. Syntax error before: ", "'('"). throw_no_parens_many_strict(Token) -> Line = case lists:keyfind(line, 1, element(2, Token)) of {line, L} -> L; false -> 0 end, throw(Line, "unexpected comma. Parentheses are required to solve ambiguity " "in nested calls. Syntax error before: ", "','"). throw_bad_atom(Line) -> throw(Line, "atom cannot be followed by an alias. If the '.' was meant to be " "part of the atom's name, the name must be quoted. Syntax error before: ", "'.'"). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_quote.erl000066400000000000000000000331161254730255300231670ustar00rootroot00000000000000-module(elixir_quote). -export([escape/2, linify/2, linify/3, linify_with_context_counter/3, quote/4]). -export([dot/5, tail_list/3, list/2]). %% Quote callbacks -include("elixir.hrl"). -define(defs(Kind), Kind == def; Kind == defp; Kind == defmacro; Kind == defmacrop). -define(lexical(Kind), Kind == import; Kind == alias; Kind == require). -compile({inline, [keyfind/2, keystore/3, keydelete/2, keyreplace/3, keynew/3]}). %% Apply the line from site call on quoted contents. %% Receives a Key to look for the default line as argument. linify(Line, Exprs) when is_integer(Line) -> do_linify(Line, line, nil, Exprs). linify(Line, Key, Exprs) when is_integer(Line) -> do_linify(Line, Key, nil, Exprs). %% Same as linify but also considers the context counter. linify_with_context_counter(Line, Var, Exprs) when is_integer(Line) -> do_linify(Line, line, Var, Exprs). do_linify(Line, Key, {Receiver, Counter} = Var, {Left, Meta, Receiver}) when is_atom(Left), is_list(Meta), Left /= '_' -> do_tuple_linify(Line, Key, Var, keynew(counter, Meta, Counter), Left, Receiver); do_linify(Line, Key, {_, Counter} = Var, {Lexical, [_|_] = Meta, [_|_] = Args}) when ?lexical(Lexical); Lexical == '__aliases__' -> do_tuple_linify(Line, Key, Var, keynew(counter, Meta, Counter), Lexical, Args); do_linify(Line, Key, Var, {Left, Meta, Right}) when is_list(Meta) -> do_tuple_linify(Line, Key, Var, Meta, Left, Right); do_linify(Line, Key, Var, {Left, Right}) -> {do_linify(Line, Key, Var, Left), do_linify(Line, Key, Var, Right)}; do_linify(Line, Key, Var, List) when is_list(List) -> [do_linify(Line, Key, Var, X) || X <- List]; do_linify(_, _, _, Else) -> Else. do_tuple_linify(Line, Key, Var, Meta, Left, Right) -> {do_linify(Line, Key, Var, Left), do_linify_meta(Line, Key, Meta), do_linify(Line, Key, Var, Right)}. do_linify_meta(0, line, Meta) -> Meta; do_linify_meta(Line, line, Meta) -> case keyfind(line, Meta) of {line, Int} when is_integer(Int), Int /= 0 -> Meta; _ -> keystore(line, Meta, Line) end; do_linify_meta(Line, Key, Meta) -> case keyfind(Key, Meta) of {Key, Int} when is_integer(Int), Int /= 0 -> keyreplace(Key, Meta, {line, Int}); _ -> do_linify_meta(Line, line, Meta) end. %% Some expressions cannot be unquoted at compilation time. %% This function is responsible for doing runtime unquoting. dot(Meta, Left, Right, Args, Context) -> annotate(dot(Meta, Left, Right, Args), Context). dot(Meta, Left, {'__aliases__', _, Args}, nil) -> {'__aliases__', Meta, [Left|Args]}; dot(Meta, Left, Right, nil) when is_atom(Right) -> case atom_to_list(Right) of "Elixir." ++ _ -> {'__aliases__', Meta, [Left, Right]}; _ -> {{'.', Meta, [Left, Right]}, Meta, []} end; dot(Meta, Left, {Right, _, Context}, nil) when is_atom(Right), is_atom(Context) -> {{'.', Meta, [Left, Right]}, Meta, []}; dot(Meta, Left, {Right, _, Args}, nil) when is_atom(Right) -> {{'.', Meta, [Left, Right]}, Meta, Args}; dot(_Meta, _Left, Right, nil) -> argument_error(<<"expected unquote after dot to return an atom, an alias or a quoted call, got: ", ('Elixir.Macro':to_string(Right))/binary>>); dot(Meta, Left, Right, Args) when is_atom(Right) -> {{'.', Meta, [Left, Right]}, Meta, Args}; dot(Meta, Left, {Right, _, Context}, Args) when is_atom(Right), is_atom(Context) -> {{'.', Meta, [Left, Right]}, Meta, Args}; dot(_Meta, _Left, Right, _Args) -> argument_error(<<"expected unquote after dot with args to return an atom or a quoted call, got: ", ('Elixir.Macro':to_string(Right))/binary>>). list(Left, Right) when is_list(Right) -> validate_list(Left), Left ++ Right. tail_list(Left, Right, Tail) when is_list(Right), is_list(Tail) -> validate_list(Left), Tail ++ Left ++ Right; tail_list(Left, Right, Tail) when is_list(Left) -> validate_list(Left), [H|T] = lists:reverse(Tail ++ Left), lists:reverse([{'|', [], [H, Right]}|T]). validate_list(List) when is_list(List) -> ok; validate_list(List) when not is_list(List) -> argument_error(<<"expected a list with quoted expressions in unquote_splicing/1, got: ", ('Elixir.Kernel':inspect(List))/binary>>). argument_error(Message) -> error('Elixir.ArgumentError':exception([{message, Message}])). %% Annotates the AST with context and other info. %% %% Note we need to delete the counter because linify %% adds the counter recursively, even inside quoted %% expressions, so we need to clean up the forms to %% allow them to get a new counter on the next expansion. annotate({Def, Meta, [{H, M, A}|T]}, Context) when ?defs(Def) -> {Def, Meta, [{H, keystore(context, M, Context), A}|T]}; annotate({{'.', _, [_, Def]} = Target, Meta, [{H, M, A}|T]}, Context) when ?defs(Def) -> {Target, Meta, [{H, keystore(context, M, Context), A}|T]}; annotate({Lexical, Meta, [_|_] = Args}, Context) when ?lexical(Lexical) -> NewMeta = keystore(context, keydelete(counter, Meta), Context), {Lexical, NewMeta, Args}; annotate(Tree, _Context) -> Tree. %% Escapes the given expression. It is similar to quote, but %% lines are kept and hygiene mechanisms are disabled. escape(Expr, Unquote) -> {Res, Q} = quote(Expr, nil, #elixir_quote{ line=true, file=nil, vars_hygiene=false, aliases_hygiene=false, imports_hygiene=false, unquote=Unquote, escape=true }, nil), {Res, Q#elixir_quote.unquoted}. %% Quotes an expression and return its quoted Elixir AST. quote({unquote_splicing, _, [_]}, _Binding, #elixir_quote{unquote=true}, _) -> argument_error(<<"unquote_splicing only works inside arguments and block contexts, " "wrap it in parens if you want it to work with one-liners">>); quote(Expr, nil, Q, E) -> do_quote(Expr, Q, E); quote(Expr, Binding, Q, E) -> Context = Q#elixir_quote.context, Vars = [ {'{}', [], [ '=', [], [ {'{}', [], [K, [], Context]}, V ] ] } || {K, V} <- Binding], {TExprs, TQ} = do_quote(Expr, Q, E), {{'{}', [], ['__block__', [], Vars ++ [TExprs] ]}, TQ}. %% Actual quoting and helpers do_quote({quote, _, Args} = Tuple, #elixir_quote{unquote=true} = Q, E) when length(Args) == 1; length(Args) == 2 -> {TTuple, TQ} = do_quote_tuple(Tuple, Q#elixir_quote{unquote=false}, E), {TTuple, TQ#elixir_quote{unquote=true}}; do_quote({unquote, _Meta, [Expr]}, #elixir_quote{unquote=true} = Q, _) -> {Expr, Q#elixir_quote{unquoted=true}}; %% Aliases do_quote({'__aliases__', Meta, [H|T]} = Alias, #elixir_quote{aliases_hygiene=true} = Q, E) when is_atom(H) and (H /= 'Elixir') -> Annotation = case elixir_aliases:expand(Alias, ?m(E, aliases), ?m(E, macro_aliases), ?m(E, lexical_tracker)) of Atom when is_atom(Atom) -> Atom; Aliases when is_list(Aliases) -> false end, AliasMeta = keystore(alias, keydelete(counter, Meta), Annotation), do_quote_tuple({'__aliases__', AliasMeta, [H|T]}, Q, E); %% Vars do_quote({Left, Meta, nil}, #elixir_quote{vars_hygiene=true} = Q, E) when is_atom(Left) -> do_quote_tuple({Left, Meta, Q#elixir_quote.context}, Q, E); %% Unquote do_quote({{{'.', Meta, [Left, unquote]}, _, [Expr]}, _, Args}, #elixir_quote{unquote=true} = Q, E) -> do_quote_call(Left, Meta, Expr, Args, Q, E); do_quote({{'.', Meta, [Left, unquote]}, _, [Expr]}, #elixir_quote{unquote=true} = Q, E) -> do_quote_call(Left, Meta, Expr, nil, Q, E); %% Imports do_quote({'&', Meta, [{'/', _, [{F, _, C}, A]}] = Args}, #elixir_quote{imports_hygiene=true} = Q, E) when is_atom(F), is_integer(A), is_atom(C) -> do_quote_fa('&', Meta, Args, F, A, Q, E); do_quote({Name, Meta, ArgsOrAtom}, #elixir_quote{imports_hygiene=true} = Q, E) when is_atom(Name) -> Arity = case is_atom(ArgsOrAtom) of true -> 0; false -> length(ArgsOrAtom) end, NewMeta = case (keyfind(import, Meta) == false) andalso elixir_dispatch:find_import(Meta, Name, Arity, E) of false -> case (Arity == 1) andalso keyfind(ambiguous_op, Meta) of {ambiguous_op, nil} -> keystore(ambiguous_op, Meta, Q#elixir_quote.context); _ -> Meta end; Receiver -> keystore(import, keystore(context, Meta, Q#elixir_quote.context), Receiver) end, Annotated = annotate({Name, NewMeta, ArgsOrAtom}, Q#elixir_quote.context), do_quote_tuple(Annotated, Q, E); do_quote({_, _, _} = Tuple, #elixir_quote{escape=false} = Q, E) -> Annotated = annotate(Tuple, Q#elixir_quote.context), do_quote_tuple(Annotated, Q, E); %% Literals do_quote({Left, Right}, #elixir_quote{unquote=true} = Q, E) when is_tuple(Left) andalso (element(1, Left) == unquote_splicing); is_tuple(Right) andalso (element(1, Right) == unquote_splicing) -> do_quote({'{}', [], [Left, Right]}, Q, E); do_quote({Left, Right}, Q, E) -> {TLeft, LQ} = do_quote(Left, Q, E), {TRight, RQ} = do_quote(Right, LQ, E), {{TLeft, TRight}, RQ}; do_quote(BitString, #elixir_quote{escape=true} = Q, _) when is_bitstring(BitString) -> case bit_size(BitString) rem 8 of 0 -> {BitString, Q}; Size -> <> = BitString, {{'<<>>', [], [{'::', [], [Bits, Size]}, Bytes]}, Q} end; do_quote(Map, #elixir_quote{escape=true} = Q, E) when is_map(Map) -> {TT, TQ} = do_quote(maps:to_list(Map), Q, E), {{'%{}', [], TT}, TQ}; do_quote(Tuple, #elixir_quote{escape=true} = Q, E) when is_tuple(Tuple) -> {TT, TQ} = do_quote(tuple_to_list(Tuple), Q, E), {{'{}', [], TT}, TQ}; do_quote(List, #elixir_quote{escape=true} = Q, E) when is_list(List) -> %% The improper case is a bit inefficient, but improper lists are rare. case reverse_improper(List) of {L} -> do_splice(L, Q, E); {L, R} -> {TL, QL} = do_splice(L, Q, E, [], []), {TR, QR} = do_quote(R, QL, E), {update_last(TL, fun(X) -> {'|', [], [X, TR]} end), QR} end; do_quote(Other, #elixir_quote{escape=true} = Q, _) when is_number(Other); is_pid(Other); is_atom(Other) -> {Other, Q}; do_quote(Fun, #elixir_quote{escape=true} = Q, _) when is_function(Fun) -> case (erlang:fun_info(Fun, env) == {env, []}) andalso (erlang:fun_info(Fun, type) == {type, external}) of true -> {Fun, Q}; false -> bad_escape(Fun) end; do_quote(Other, #elixir_quote{escape=true}, _) -> bad_escape(Other); do_quote(List, Q, E) when is_list(List) -> do_splice(lists:reverse(List), Q, E); do_quote(Other, Q, _) -> {Other, Q}. %% Quote helpers bad_escape(Arg) -> argument_error(<<"cannot escape ", ('Elixir.Kernel':inspect(Arg, []))/binary, ". ", "The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, ", "pids and remote functions in the format &Mod.fun/arity">>). do_quote_call(Left, Meta, Expr, Args, Q, E) -> All = [meta(Meta, Q), Left, {unquote, Meta, [Expr]}, Args, Q#elixir_quote.context], {TAll, TQ} = lists:mapfoldl(fun(X, Acc) -> do_quote(X, Acc, E) end, Q, All), {{{'.', Meta, [elixir_quote, dot]}, Meta, TAll}, TQ}. do_quote_fa(Target, Meta, Args, F, A, Q, E) -> NewMeta = case (keyfind(import_fa, Meta) == false) andalso elixir_dispatch:find_import(Meta, F, A, E) of false -> Meta; Receiver -> keystore(import_fa, Meta, {Receiver, Q#elixir_quote.context}) end, do_quote_tuple({Target, NewMeta, Args}, Q, E). do_quote_tuple({Left, Meta, Right}, Q, E) -> {TLeft, LQ} = do_quote(Left, Q, E), {TRight, RQ} = do_quote(Right, LQ, E), {{'{}', [], [TLeft, meta(Meta, Q), TRight]}, RQ}. meta(Meta, Q) -> file(line(Meta, Q), Q). file(Meta, #elixir_quote{file=nil}) -> Meta; file(Meta, #elixir_quote{file=File}) -> [{file, File}|Meta]. line(Meta, #elixir_quote{file=File}) when File /= nil -> [case KV of {line, V} -> {keep, V}; _ -> KV end || KV <- Meta]; line(Meta, #elixir_quote{line=true}) -> Meta; line(Meta, #elixir_quote{line=false}) -> keydelete(line, Meta); line(Meta, #elixir_quote{line=Line}) -> keystore(line, Meta, Line). reverse_improper(L) -> reverse_improper(L, []). reverse_improper([], Acc) -> {Acc}; reverse_improper([H|T], Acc) when is_list(T) -> reverse_improper(T, [H|Acc]); reverse_improper([H|T], Acc) -> {[H|Acc], T}. update_last([], _) -> []; update_last([H], F) -> [F(H)]; update_last([H|T], F) -> [H|update_last(T, F)]. keyfind(Key, Meta) -> lists:keyfind(Key, 1, Meta). keydelete(Key, Meta) -> lists:keydelete(Key, 1, Meta). keystore(_Key, Meta, nil) -> Meta; keystore(Key, Meta, Value) -> lists:keystore(Key, 1, Meta, {Key, Value}). keyreplace(Key, Meta, {Key, _V}) -> Meta; keyreplace(Key, Meta, Tuple) -> lists:keyreplace(Key, 1, Meta, Tuple). keynew(Key, Meta, Value) -> case keyfind(Key, Meta) of {Key, _} -> Meta; _ -> keystore(Key, Meta, Value) end. %% Quote splicing do_splice([{'|', Meta, [{unquote_splicing, _, [Left]}, Right]}|T], #elixir_quote{unquote=true} = Q, E) -> %% Process the remaining entries on the list. %% For [1, 2, 3, unquote_splicing(arg)|tail], this will quote %% 1, 2 and 3, which could even be unquotes. {TT, QT} = do_splice(T, Q, E, [], []), {TR, QR} = do_quote(Right, QT, E), {do_runtime_list(Meta, tail_list, [Left, TR, TT]), QR#elixir_quote{unquoted=true}}; do_splice(List, Q, E) -> do_splice(List, Q, E, [], []). do_splice([{unquote_splicing, Meta, [Expr]}|T], #elixir_quote{unquote=true} = Q, E, Buffer, Acc) -> do_splice(T, Q#elixir_quote{unquoted=true}, E, [], do_runtime_list(Meta, list, [Expr, do_join(Buffer, Acc)])); do_splice([H|T], Q, E, Buffer, Acc) -> {TH, TQ} = do_quote(H, Q, E), do_splice(T, TQ, E, [TH|Buffer], Acc); do_splice([], Q, _E, Buffer, Acc) -> {do_join(Buffer, Acc), Q}. do_join(Left, []) -> Left; do_join([], Right) -> Right; do_join(Left, Right) -> {{'.', [], [erlang, '++']}, [], [Left, Right]}. do_runtime_list(Meta, Fun, Args) -> {{'.', Meta, [elixir_quote, Fun]}, Meta, Args}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_rewrite.erl000066400000000000000000000216711254730255300235160ustar00rootroot00000000000000-module(elixir_rewrite). -export([rewrite/5, inline/3]). %% Convenience variables -define(hidden, [{line, -1}]). -define(atom, 'Elixir.Atom'). -define(enum, 'Elixir.Enum'). -define(float, 'Elixir.Float'). -define(io, 'Elixir.IO'). -define(integer, 'Elixir.Integer'). -define(kernel, 'Elixir.Kernel'). -define(list, 'Elixir.List'). -define(map, 'Elixir.Map'). -define(node, 'Elixir.Node'). -define(port, 'Elixir.Port'). -define(process, 'Elixir.Process'). -define(string, 'Elixir.String'). -define(string_chars, 'Elixir.String.Chars'). -define(system, 'Elixir.System'). -define(tuple, 'Elixir.Tuple'). %% Inline %% Inline rules are straight-forward, they keep the same %% number and order of arguments and show up on captures. inline(?atom, to_char_list, 1) -> {erlang, atom_to_list}; inline(?io, iodata_length, 1) -> {erlang, iolist_size}; inline(?io, iodata_to_binary, 1) -> {erlang, iolist_to_binary}; inline(?integer, to_string, 1) -> {erlang, integer_to_binary}; inline(?integer, to_string, 2) -> {erlang, integer_to_binary}; inline(?integer, to_char_list, 1) -> {erlang, integer_to_list}; inline(?integer, to_char_list, 2) -> {erlang, integer_to_list}; inline(?float, to_string, 1) -> {erlang, float_to_binary}; inline(?float, to_char_list, 1) -> {erlang, float_to_list}; inline(?list, to_atom, 1) -> {erlang, list_to_atom}; inline(?list, to_existing_atom, 1) -> {erlang, list_to_existing_atom}; inline(?list, to_float, 1) -> {erlang, list_to_float}; inline(?list, to_integer, 1) -> {erlang, list_to_integer}; inline(?list, to_integer, 2) -> {erlang, list_to_integer}; inline(?list, to_tuple, 1) -> {erlang, list_to_tuple}; inline(?kernel, '+', 2) -> {erlang, '+'}; inline(?kernel, '-', 2) -> {erlang, '-'}; inline(?kernel, '+', 1) -> {erlang, '+'}; inline(?kernel, '-', 1) -> {erlang, '-'}; inline(?kernel, '*', 2) -> {erlang, '*'}; inline(?kernel, '/', 2) -> {erlang, '/'}; inline(?kernel, '++', 2) -> {erlang, '++'}; inline(?kernel, '--', 2) -> {erlang, '--'}; inline(?kernel, 'not', 1) -> {erlang, 'not'}; inline(?kernel, '<', 2) -> {erlang, '<'}; inline(?kernel, '>', 2) -> {erlang, '>'}; inline(?kernel, '<=', 2) -> {erlang, '=<'}; inline(?kernel, '>=', 2) -> {erlang, '>='}; inline(?kernel, '==', 2) -> {erlang, '=='}; inline(?kernel, '!=', 2) -> {erlang, '/='}; inline(?kernel, '===', 2) -> {erlang, '=:='}; inline(?kernel, '!==', 2) -> {erlang, '=/='}; inline(?kernel, abs, 1) -> {erlang, abs}; inline(?kernel, apply, 2) -> {erlang, apply}; inline(?kernel, apply, 3) -> {erlang, apply}; inline(?kernel, binary_part, 3) -> {erlang, binary_part}; inline(?kernel, bit_size, 1) -> {erlang, bit_size}; inline(?kernel, byte_size, 1) -> {erlang, byte_size}; inline(?kernel, 'div', 2) -> {erlang, 'div'}; inline(?kernel, exit, 1) -> {erlang, exit}; inline(?kernel, hd, 1) -> {erlang, hd}; inline(?kernel, is_atom, 1) -> {erlang, is_atom}; inline(?kernel, is_binary, 1) -> {erlang, is_binary}; inline(?kernel, is_bitstring, 1) -> {erlang, is_bitstring}; inline(?kernel, is_boolean, 1) -> {erlang, is_boolean}; inline(?kernel, is_float, 1) -> {erlang, is_float}; inline(?kernel, is_function, 1) -> {erlang, is_function}; inline(?kernel, is_function, 2) -> {erlang, is_function}; inline(?kernel, is_integer, 1) -> {erlang, is_integer}; inline(?kernel, is_list, 1) -> {erlang, is_list}; inline(?kernel, is_map, 1) -> {erlang, is_map}; inline(?kernel, is_number, 1) -> {erlang, is_number}; inline(?kernel, is_pid, 1) -> {erlang, is_pid}; inline(?kernel, is_port, 1) -> {erlang, is_port}; inline(?kernel, is_reference, 1) -> {erlang, is_reference}; inline(?kernel, is_tuple, 1) -> {erlang, is_tuple}; inline(?kernel, length, 1) -> {erlang, length}; inline(?kernel, make_ref, 0) -> {erlang, make_ref}; inline(?kernel, map_size, 1) -> {erlang, map_size}; inline(?kernel, max, 2) -> {erlang, max}; inline(?kernel, min, 2) -> {erlang, min}; inline(?kernel, node, 0) -> {erlang, node}; inline(?kernel, node, 1) -> {erlang, node}; inline(?kernel, 'rem', 2) -> {erlang, 'rem'}; inline(?kernel, round, 1) -> {erlang, round}; inline(?kernel, self, 0) -> {erlang, self}; inline(?kernel, send, 2) -> {erlang, send}; inline(?kernel, spawn, 1) -> {erlang, spawn}; inline(?kernel, spawn, 3) -> {erlang, spawn}; inline(?kernel, spawn_link, 1) -> {erlang, spawn_link}; inline(?kernel, spawn_link, 3) -> {erlang, spawn_link}; inline(?kernel, spawn_monitor, 1) -> {erlang, spawn_monitor}; inline(?kernel, spawn_monitor, 3) -> {erlang, spawn_monitor}; inline(?kernel, throw, 1) -> {erlang, throw}; inline(?kernel, tl, 1) -> {erlang, tl}; inline(?kernel, trunc, 1) -> {erlang, trunc}; inline(?kernel, tuple_size, 1) -> {erlang, tuple_size}; inline(?map, keys, 1) -> {maps, keys}; inline(?map, merge, 2) -> {maps, merge}; inline(?map, size, 1) -> {maps, size}; inline(?map, values, 1) -> {maps, values}; inline(?map, to_list, 1) -> {maps, to_list}; inline(?node, spawn, 2) -> {erlang, spawn}; inline(?node, spawn, 3) -> {erlang, spawn_opt}; inline(?node, spawn, 4) -> {erlang, spawn}; inline(?node, spawn, 5) -> {erlang, spawn_opt}; inline(?node, spawn_link, 2) -> {erlang, spawn_link}; inline(?node, spawn_link, 4) -> {erlang, spawn_link}; inline(?process, exit, 2) -> {erlang, exit}; inline(?process, spawn, 2) -> {erlang, spawn_opt}; inline(?process, spawn, 4) -> {erlang, spawn_opt}; inline(?process, demonitor, 1) -> {erlang, demonitor}; inline(?process, demonitor, 2) -> {erlang, demonitor}; inline(?process, link, 1) -> {erlang, link}; inline(?process, unlink, 1) -> {erlang, unlink}; inline(?process, hibernate, 3) -> {erlang, hibernate}; inline(?port, open, 2) -> {erlang, open_port}; inline(?port, call, 3) -> {erlang, port_call}; inline(?port, close, 1) -> {erlang, port_close}; inline(?port, command, 2) -> {erlang, port_command}; inline(?port, command, 3) -> {erlang, port_command}; inline(?port, connect, 2) -> {erlang, port_connect}; inline(?port, control, 3) -> {erlang, port_control}; inline(?port, list, 0) -> {erlang, ports}; inline(?string, to_float, 1) -> {erlang, binary_to_float}; inline(?string, to_integer, 1) -> {erlang, binary_to_integer}; inline(?string, to_integer, 2) -> {erlang, binary_to_integer}; inline(?system, stacktrace, 0) -> {erlang, get_stacktrace}; inline(?tuple, to_list, 1) -> {erlang, tuple_to_list}; inline(?tuple, append, 2) -> {erlang, append_element}; inline(_, _, _) -> false. %% Rewrite rules %% Rewrite rules are more complex than regular inlining code. %% It receives all remote call arguments and return quoted %% expressions with the new environment. %% Complex rewrite rules rewrite(?string_chars, _DotMeta, 'to_string', _Meta, [String]) when is_binary(String) -> String; rewrite(?string_chars, DotMeta, 'to_string', Meta, [String]) -> Var = {'_rewrite', ?hidden, nil}, Guard = {{'.', ?hidden, [erlang, is_binary]}, ?hidden, [Var]}, Slow = remote(?string_chars, DotMeta, 'to_string', Meta, [Var]), Fast = Var, {'case', ?hidden, [String, [{do, [{'->', ?hidden, [[{'when', ?hidden, [Var, Guard]}], Fast]}, {'->', ?hidden, [[Var], Slow]}] }]]}; rewrite(?enum, DotMeta, 'reverse', Meta, [List]) when is_list(List) -> remote(lists, DotMeta, 'reverse', Meta, [List]); rewrite(?enum, DotMeta, 'reverse', Meta, [List]) -> Var = {'_rewrite', ?hidden, nil}, Guard = {{'.', ?hidden, [erlang, is_list]}, ?hidden, [Var]}, Slow = remote(?enum, DotMeta, 'reverse', Meta, [Var]), Fast = remote(lists, DotMeta, 'reverse', Meta, [Var]), {'case', ?hidden, [List, [{do, [{'->', ?hidden, [[{'when', ?hidden, [Var, Guard]}], Fast]}, {'->', ?hidden, [[Var], Slow]}] }]]}; rewrite(Receiver, DotMeta, Right, Meta, Args) -> {EReceiver, ERight, EArgs} = rewrite(Receiver, Right, Args), remote(EReceiver, DotMeta, ERight, Meta, EArgs). %% Simple rewrite rules rewrite(?atom, to_string, [Arg]) -> {erlang, atom_to_binary, [Arg, utf8]}; rewrite(?kernel, elem, [Tuple, Index]) -> {erlang, element, [increment(Index), Tuple]}; rewrite(?kernel, put_elem, [Tuple, Index, Value]) -> {erlang, setelement, [increment(Index), Tuple, Value]}; rewrite(?map, 'has_key?', [Map, Key]) -> {maps, is_key, [Key, Map]}; rewrite(?map, fetch, [Map, Key]) -> {maps, find, [Key, Map]}; rewrite(?map, put, [Map, Key, Value]) -> {maps, put, [Key, Value, Map]}; rewrite(?map, delete, [Map, Key]) -> {maps, remove, [Key, Map]}; rewrite(?process, monitor, [Arg]) -> {erlang, monitor, [process, Arg]}; rewrite(?string, to_atom, [Arg]) -> {erlang, binary_to_atom, [Arg, utf8]}; rewrite(?string, to_existing_atom, [Arg]) -> {erlang, binary_to_existing_atom, [Arg, utf8]}; rewrite(?tuple, insert_at, [Tuple, Index, Term]) -> {erlang, insert_element, [increment(Index), Tuple, Term]}; rewrite(?tuple, delete_at, [Tuple, Index]) -> {erlang, delete_element, [increment(Index), Tuple]}; rewrite(?tuple, duplicate, [Data, Size]) -> {erlang, make_tuple, [Size, Data]}; rewrite(Receiver, Fun, Args) -> {Receiver, Fun, Args}. %% Rewrite helpers remote(Receiver, DotMeta, Right, Meta, Args) -> {{'.', DotMeta, [Receiver, Right]}, Meta, Args}. increment(Number) when is_number(Number) -> Number + 1; increment(Other) -> {{'.', [], [erlang, '+']}, [], [Other, 1]}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_scope.erl000066400000000000000000000117121254730255300231410ustar00rootroot00000000000000%% Convenience functions used to manipulate scope and its variables. -module(elixir_scope). -export([translate_var/4, build_var/2, context_info/1, load_binding/2, dump_binding/2, mergev/2, mergec/2, mergef/2, merge_vars/2, merge_opt_vars/2, format_error/1 ]). -include("elixir.hrl"). %% VAR HANDLING translate_var(Meta, Name, Kind, S) when is_atom(Kind); is_integer(Kind) -> Line = ?line(Meta), Tuple = {Name, Kind}, Vars = S#elixir_scope.vars, case orddict:find({Name, Kind}, Vars) of {ok, {Current, _}} -> Exists = true; error -> Current = nil, Exists = false end, case S#elixir_scope.context of match -> MatchVars = S#elixir_scope.match_vars, case Exists andalso ordsets:is_element(Tuple, MatchVars) of true -> warn_underscored_var(Line, S#elixir_scope.file, Name, Kind), {{var, Line, Current}, S}; false -> %% We attempt to give vars a nice name because we %% still use the unused vars warnings from erl_lint. %% %% Once we move the warning to Elixir compiler, we %% can name vars as _@COUNTER. {NewVar, Counter, NS} = if Kind /= nil -> build_var('_', S); true -> build_var(Name, S) end, FS = NS#elixir_scope{ vars=orddict:store(Tuple, {NewVar, Counter}, Vars), match_vars=ordsets:add_element(Tuple, MatchVars), export_vars=case S#elixir_scope.export_vars of nil -> nil; EV -> orddict:store(Tuple, {NewVar, Counter}, EV) end }, {{var, Line, NewVar}, FS} end; _ when Exists -> {{var, Line, Current}, S} end. build_var(Key, S) -> New = orddict:update_counter(Key, 1, S#elixir_scope.counter), Cnt = orddict:fetch(Key, New), {elixir_utils:atom_concat([Key, "@", Cnt]), Cnt, S#elixir_scope{counter=New}}. context_info(Kind) when Kind == nil; is_integer(Kind) -> ""; context_info(Kind) -> io_lib:format(" (context ~ts)", [elixir_aliases:inspect(Kind)]). warn_underscored_var(Line, File, Name, Kind) -> case atom_to_list(Name) of "_@" ++ _ -> ok; %% Automatically generated variables "_" ++ _ -> elixir_errors:form_warn([{line, Line}], File, ?MODULE, {unused_match, Name, Kind}); _ -> ok end. %% SCOPE MERGING %% Receives two scopes and return a new scope based on %% the second with their variables merged. mergev(S1, S2) -> S2#elixir_scope{ vars=merge_vars(S1#elixir_scope.vars, S2#elixir_scope.vars), export_vars=merge_opt_vars(S1#elixir_scope.export_vars, S2#elixir_scope.export_vars) }. %% Receives two scopes and return the first scope with %% counters and flags from the later. mergec(S1, S2) -> S1#elixir_scope{ counter=S2#elixir_scope.counter, super=S2#elixir_scope.super, caller=S2#elixir_scope.caller }. %% Similar to mergec but does not merge the user vars counter. mergef(S1, S2) -> S1#elixir_scope{ super=S2#elixir_scope.super, caller=S2#elixir_scope.caller }. %% Mergers. merge_vars(V, V) -> V; merge_vars(V1, V2) -> orddict:merge(fun var_merger/3, V1, V2). merge_opt_vars(nil, _C2) -> nil; merge_opt_vars(_C1, nil) -> nil; merge_opt_vars(C, C) -> C; merge_opt_vars(C1, C2) -> orddict:merge(fun var_merger/3, C1, C2). var_merger(_Var, {_, V1} = K1, {_, V2}) when V1 > V2 -> K1; var_merger(_Var, _K1, K2) -> K2. %% BINDINGS load_binding(Binding, Scope) -> {NewBinding, NewVars, NewCounter} = load_binding(Binding, [], [], 0), {NewBinding, Scope#elixir_scope{ vars=NewVars, counter=[{'_', NewCounter}] }}. load_binding([{Key, Value}|T], Binding, Vars, Counter) -> Actual = case Key of {_Name, _Kind} -> Key; Name when is_atom(Name) -> {Name, nil} end, InternalName = elixir_utils:atom_concat(["_@", Counter]), load_binding(T, orddict:store(InternalName, Value, Binding), orddict:store(Actual, {InternalName, 0}, Vars), Counter + 1); load_binding([], Binding, Vars, Counter) -> {Binding, Vars, Counter}. dump_binding(Binding, #elixir_scope{vars=Vars}) -> dump_binding(Vars, Binding, []). dump_binding([{{Var, Kind} = Key, {InternalName, _}}|T], Binding, Acc) when is_atom(Kind) -> Actual = case Kind of nil -> Var; _ -> Key end, Value = proplists:get_value(InternalName, Binding, nil), dump_binding(T, Binding, orddict:store(Actual, Value, Acc)); dump_binding([_|T], Binding, Acc) -> dump_binding(T, Binding, Acc); dump_binding([], _Binding, Acc) -> Acc. %% Errors format_error({unused_match, Name, Kind}) -> io_lib:format("the underscored variable \"~ts\"~ts appears more than once in a " "match. This means the pattern will only match if all \"~ts\" bind " "to the same value. If this is the intended behaviour, please " "remove the leading underscore from the variable name, otherwise " "give the variables different names", [Name, context_info(Kind), Name]). elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_sup.erl000066400000000000000000000025341254730255300226410ustar00rootroot00000000000000-module(elixir_sup). -behaviour(supervisor). -export([init/1, start_link/0]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, ok). init(ok) -> Workers = [ { elixir_config, {elixir_config, start_link, []}, permanent, % Restart = permanent | transient | temporary 2000, % Shutdown = brutal_kill | int() >= 0 | infinity worker, % Type = worker | supervisor [elixir_config] % Modules = [Module] | dynamic }, { elixir_code_server, {elixir_code_server, start_link, []}, permanent, % Restart = permanent | transient | temporary 2000, % Shutdown = brutal_kill | int() >= 0 | infinity worker, % Type = worker | supervisor [elixir_code_server] % Modules = [Module] | dynamic }, { elixir_counter, {elixir_counter, start_link, []}, permanent, % Restart = permanent | transient | temporary 2000, % Shutdown = brutal_kill | int() >= 0 | infinity worker, % Type = worker | supervisor [elixir_counter] % Modules = [Module] | dynamic } ], {ok, {{one_for_one, 3, 10}, Workers}}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_tokenizer.erl000066400000000000000000001215351254730255300240470ustar00rootroot00000000000000-module(elixir_tokenizer). -include("elixir.hrl"). -export([tokenize/3, tokenize/4]). -import(elixir_interpolation, [unescape_tokens/1]). -define(at_op(T), T == $@). -define(capture_op(T), T == $&). -define(unary_op(T), T == $!; T == $^). -define(unary_op3(T1, T2, T3), T1 == $~, T2 == $~, T3 == $~). -define(hat_op3(T1, T2, T3), T1 == $^, T2 == $^, T3 == $^). -define(two_op(T1, T2), T1 == $+, T2 == $+; T1 == $-, T2 == $-; T1 == $<, T2 == $>; T1 == $., T2 == $.). -define(mult_op(T), T == $* orelse T == $/). -define(dual_op(T), T == $+ orelse T == $-). -define(arrow_op3(T1, T2, T3), T1 == $<, T2 == $<, T3 == $<; T1 == $>, T2 == $>, T3 == $>; T1 == $~, T2 == $>, T3 == $>; T1 == $<, T2 == $<, T3 == $~; T1 == $<, T2 == $~, T3 == $>; T1 == $<, T2 == $|, T3 == $>). -define(arrow_op(T1, T2), T1 == $|, T2 == $>; T1 == $~, T2 == $>; T1 == $<, T2 == $~). -define(rel_op(T), T == $<; T == $>). -define(rel_op2(T1, T2), T1 == $<, T2 == $=; T1 == $>, T2 == $=). -define(comp_op2(T1, T2), T1 == $=, T2 == $=; T1 == $=, T2 == $~; T1 == $!, T2 == $=). -define(comp_op3(T1, T2, T3), T1 == $=, T2 == $=, T3 == $=; T1 == $!, T2 == $=, T3 == $=). -define(and_op(T1, T2), T1 == $&, T2 == $&). -define(or_op(T1, T2), T1 == $|, T2 == $|). -define(and_op3(T1, T2, T3), T1 == $&, T2 == $&, T3 == $&). -define(or_op3(T1, T2, T3), T1 == $|, T2 == $|, T3 == $|). -define(match_op(T), T == $=). -define(in_match_op(T1, T2), T1 == $<, T2 == $-; T1 == $\\, T2 == $\\). -define(stab_op(T1, T2), T1 == $-, T2 == $>). -define(type_op(T1, T2), T1 == $:, T2 == $:). -define(pipe_op(T), T == $|). tokenize(String, Line, Column, #elixir_tokenizer{} = Scope) -> tokenize(String, Line, Column, Scope, []); tokenize(String, Line, Column, Opts) -> File = case lists:keyfind(file, 1, Opts) of {file, V1} -> V1; false -> <<"nofile">> end, Existing = case lists:keyfind(existing_atoms_only, 1, Opts) of {existing_atoms_only, true} -> true; false -> false end, Check = case lists:keyfind(check_terminators, 1, Opts) of {check_terminators, false} -> false; false -> true end, tokenize(String, Line, Column, #elixir_tokenizer{ file=File, existing_atoms_only=Existing, check_terminators=Check }). tokenize(String, Line, Opts) -> tokenize(String, Line, 1, Opts). tokenize([], Line, Column, #elixir_tokenizer{terminators=[]}, Tokens) -> {ok, Line, Column, lists:reverse(Tokens)}; tokenize([], EndLine, _Column, #elixir_tokenizer{terminators=[{Start, {StartLine, _, _}}|_]}, Tokens) -> End = terminator(Start), Message = io_lib:format("missing terminator: ~ts (for \"~ts\" starting at line ~B)", [End, Start, StartLine]), {error, {EndLine, Message, []}, [], Tokens}; % Base integers tokenize([$0, $x, H|T], Line, Column, Scope, Tokens) when ?is_hex(H) -> {Rest, Number, Length} = tokenize_hex([H|T], []), tokenize(Rest, Line, Column + 2 + Length, Scope, [{number, {Line, Column, Column + 2 + Length}, Number}|Tokens]); tokenize([$0, $b, H|T], Line, Column, Scope, Tokens) when ?is_bin(H) -> {Rest, Number, Length} = tokenize_bin([H|T], []), tokenize(Rest, Line, Column + 2 + Length, Scope, [{number, {Line, Column, Column + 2 + Length}, Number}|Tokens]); tokenize([$0, $o, H|T], Line, Column, Scope, Tokens) when ?is_octal(H) -> {Rest, Number, Length} = tokenize_octal([H|T], []), tokenize(Rest, Line, Column + 2 + Length, Scope, [{number, {Line, Column, Column + 2 + Length}, Number}|Tokens]); % Comments tokenize([$#|String], Line, Column, Scope, Tokens) -> Rest = tokenize_comment(String), tokenize(Rest, Line, Column, Scope, Tokens); % Sigils tokenize([$~, S, H, H, H|T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H), ?is_upcase(S) orelse ?is_downcase(S) -> case extract_heredoc_with_interpolation(Line, Column, Scope, ?is_downcase(S), T, H) of {ok, NewLine, NewColumn, Parts, Rest} -> {Final, Modifiers} = collect_modifiers(Rest, []), tokenize(Final, NewLine, NewColumn, Scope, [{sigil, {Line, Column, NewColumn}, S, Parts, Modifiers}|Tokens]); {error, Reason} -> {error, Reason, Original, Tokens} end; tokenize([$~, S, H|T] = Original, Line, Column, Scope, Tokens) when ?is_sigil(H), ?is_upcase(S) orelse ?is_downcase(S) -> case elixir_interpolation:extract(Line, Column + 3, Scope, ?is_downcase(S), T, sigil_terminator(H)) of {NewLine, NewColumn, Parts, Rest} -> {Final, Modifiers} = collect_modifiers(Rest, []), tokenize(Final, NewLine, NewColumn, Scope, [{sigil, {Line, Column, NewColumn}, S, Parts, Modifiers}|Tokens]); {error, Reason} -> Sigil = [$~, S, H], interpolation_error(Reason, Original, Tokens, " (for sigil ~ts starting at line ~B)", [Sigil, Line]) end; % Char tokens tokenize([$?, $\\, $x, ${,A,B,C,D,E,F,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D), ?is_hex(E), ?is_hex(F) -> Char = escape_char([$\\, $x, ${,A,B,C,D,E,F,$}]), tokenize(T, Line, Column + 11, Scope, [{number, {Line, Column, Column + 11}, Char}|Tokens]); tokenize([$?, $\\, $x, ${,A,B,C,D,E,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D), ?is_hex(E) -> Char = escape_char([$\\, $x, ${,A,B,C,D,E,$}]), tokenize(T, Line, Column + 10, Scope, [{number, {Line, Column, Column + 10}, Char}|Tokens]); tokenize([$?, $\\, $x, ${,A,B,C,D,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D) -> Char = escape_char([$\\, $x, ${,A,B,C,D,$}]), tokenize(T, Line, Column + 9, Scope, [{number, {Line, Column, Column + 9}, Char}|Tokens]); tokenize([$?, $\\, $x, ${,A,B,C,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B), ?is_hex(C) -> Char = escape_char([$\\, $x, ${,A,B,C,$}]), tokenize(T, Line, Column + 8, Scope, [{number, {Line, Column, Column + 8}, Char}|Tokens]); tokenize([$?, $\\, $x, ${,A,B,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B) -> Char = escape_char([$\\, $x, ${,A,B,$}]), tokenize(T, Line, Column + 7, Scope, [{number, {Line, Column, Column + 7}, Char}|Tokens]); tokenize([$?, $\\, $x, ${,A,$}|T], Line, Column, Scope, Tokens) when ?is_hex(A) -> Char = escape_char([$\\, $x, ${,A,$}]), tokenize(T, Line, Column + 6, Scope, [{number, {Line, Column, Column + 6}, Char}|Tokens]); tokenize([$?, $\\, $x, A, B|T], Line, Column, Scope, Tokens) when ?is_hex(A), ?is_hex(B) -> Char = escape_char([$\\, $x, A, B]), tokenize(T, Line, Column + 5, Scope, [{number, {Line, Column, Column + 5}, Char}|Tokens]); tokenize([$?, $\\, $x, A|T], Line, Column, Scope, Tokens) when ?is_hex(A) -> Char = escape_char([$\\, $x, A]), tokenize(T, Line, Column + 4, Scope, [{number, {Line, Column, Column + 4}, Char}|Tokens]); tokenize([$?, $\\, H|T], Line, Column, Scope, Tokens) -> Char = elixir_interpolation:unescape_map(H), tokenize(T, Line, Column + 3, Scope, [{number, {Line, Column, Column + 3}, Char}|Tokens]); tokenize([$?, Char|T], Line, Column, Scope, Tokens) -> case handle_char(Char) of {Escape, Name} -> Msg = io_lib:format("found ? followed by codepoint 0x~.16B (~ts), please use ~ts instead", [Char, Name, Escape]), elixir_errors:warn(Line, Scope#elixir_tokenizer.file, Msg); false -> ok end, tokenize(T, Line, Column + 2, Scope, [{number, {Line, Column, Column + 2}, Char}|Tokens]); % Heredocs tokenize("\"\"\"" ++ T, Line, Column, Scope, Tokens) -> handle_heredocs(T, Line, Column, $", Scope, Tokens); tokenize("'''" ++ T, Line, Column, Scope, Tokens) -> handle_heredocs(T, Line, Column, $', Scope, Tokens); % Strings tokenize([$"|T], Line, Column, Scope, Tokens) -> handle_strings(T, Line, Column + 1, $", Scope, Tokens); tokenize([$'|T], Line, Column, Scope, Tokens) -> handle_strings(T, Line, Column + 1, $', Scope, Tokens); % Atoms tokenize([$:, H|T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H) -> case elixir_interpolation:extract(Line, Column + 2, Scope, true, T, H) of {NewLine, NewColumn, Parts, Rest} -> Unescaped = unescape_tokens(Parts), Key = case Scope#elixir_tokenizer.existing_atoms_only of true -> atom_safe; false -> atom_unsafe end, tokenize(Rest, NewLine, NewColumn, Scope, [{Key, {Line, Column, NewColumn}, Unescaped}|Tokens]); {error, Reason} -> interpolation_error(Reason, Original, Tokens, " (for atom starting at line ~B)", [Line]) end; tokenize([$:, T|String] = Original, Line, Column, Scope, Tokens) when ?is_atom_start(T) -> {Rest, Part, Length} = tokenize_atom([T|String], []), case unsafe_to_atom(Part, Line, Scope) of {ok, Atom} -> tokenize(Rest, Line, Column + 1 + Length, Scope, [{atom, {Line, Column, Column + 1 + Length}, Atom}|Tokens]); {error, Reason} -> {error, Reason, Original, Tokens} end; % %% Special atom identifiers / operators tokenize(":..." ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 4, Scope, [{atom, {Line, Column, Column + 4}, '...'}|Tokens]); tokenize(":<<>>" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 5, Scope, [{atom, {Line, Column, Column + 5}, '<<>>'}|Tokens]); tokenize(":%{}" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 4, Scope, [{atom, {Line, Column, Column + 4}, '%{}'}|Tokens]); tokenize(":%" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 2, Scope, [{atom, {Line, Column, Column + 2}, '%'}|Tokens]); tokenize(":{}" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 3, Scope, [{atom, {Line, Column, Column + 3}, '{}'}|Tokens]); tokenize("...:" ++ Rest, Line, Column, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + 4, Scope, [{kw_identifier, {Line, Column, Column + 4}, '...'}|Tokens]); tokenize("<<>>:" ++ Rest, Line, Column, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + 5, Scope, [{kw_identifier, {Line, Column, Column + 5}, '<<>>'}|Tokens]); tokenize("%{}:" ++ Rest, Line, Column, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + 4, Scope, [{kw_identifier, {Line, Column, Column + 4}, '%{}'}|Tokens]); tokenize("%:" ++ Rest, Line, Column, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + 2, Scope, [{kw_identifier, {Line, Column, Column + 2}, '%'}|Tokens]); tokenize("{}:" ++ Rest, Line, Column, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + 3, Scope, [{kw_identifier, {Line, Column, Column + 3}, '{}'}|Tokens]); % ## Three Token Operators tokenize([$:, T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?unary_op3(T1, T2, T3); ?comp_op3(T1, T2, T3); ?and_op3(T1, T2, T3); ?or_op3(T1, T2, T3); ?arrow_op3(T1, T2, T3); ?hat_op3(T1, T2, T3) -> tokenize(Rest, Line, Column + 4, Scope, [{atom, {Line, Column, Column + 4}, list_to_atom([T1, T2, T3])}|Tokens]); % ## Two Token Operators tokenize([$:, T1, T2|Rest], Line, Column, Scope, Tokens) when ?comp_op2(T1, T2); ?rel_op2(T1, T2); ?and_op(T1, T2); ?or_op(T1, T2); ?arrow_op(T1, T2); ?in_match_op(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2); ?type_op(T1, T2) -> tokenize(Rest, Line, Column + 3, Scope, [{atom, {Line, Column, Column + 3}, list_to_atom([T1, T2])}|Tokens]); % ## Single Token Operators tokenize([$:, T|Rest], Line, Column, Scope, Tokens) when ?at_op(T); ?unary_op(T); ?capture_op(T); ?dual_op(T); ?mult_op(T); ?rel_op(T); ?match_op(T); ?pipe_op(T); T == $. -> tokenize(Rest, Line, Column + 2, Scope, [{atom, {Line, Column, Column + 2}, list_to_atom([T])}|Tokens]); % End of line tokenize(";" ++ Rest, Line, Column, Scope, []) -> tokenize(Rest, Line, Column + 1, Scope, [{';', {Line, Column, Column + 1}}]); tokenize(";" ++ Rest, Line, Column, Scope, [Top|_] = Tokens) when element(1, Top) /= ';' -> tokenize(Rest, Line, Column + 1, Scope, [{';', {Line, Column, Column + 1}}|Tokens]); tokenize("\\" = Original, Line, _Column, _Scope, Tokens) -> {error, {Line, "invalid escape \\ at end of file", []}, Original, Tokens}; tokenize("\\\n" = Original, Line, _Column, _Scope, Tokens) -> {error, {Line, "invalid escape \\ at end of file", []}, Original, Tokens}; tokenize("\\\r\n" = Original, Line, _Column, _Scope, Tokens) -> {error, {Line, "invalid escape \\ at end of file", []}, Original, Tokens}; tokenize("\\\n" ++ Rest, Line, _Column, Scope, Tokens) -> tokenize(Rest, Line + 1, 1, Scope, Tokens); tokenize("\\\r\n" ++ Rest, Line, _Column, Scope, Tokens) -> tokenize(Rest, Line + 1, 1, Scope, Tokens); tokenize("\n" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line + 1, 1, Scope, eol(Line, Column, Tokens)); tokenize("\r\n" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line + 1, 1, Scope, eol(Line, Column, Tokens)); % Stand-alone tokens tokenize("..." ++ Rest, Line, Column, Scope, Tokens) -> Token = check_call_identifier(identifier, Line, Column, 3, '...', Rest), tokenize(Rest, Line, Column + 3, Scope, [Token|Tokens]); tokenize("=>" ++ Rest, Line, Column, Scope, Tokens) -> tokenize(Rest, Line, Column + 2, Scope, add_token_with_nl({assoc_op, {Line, Column, Column + 2}, '=>'}, Tokens)); % ## Three token operators tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?unary_op3(T1, T2, T3) -> handle_unary_op(Rest, Line, Column, unary_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?comp_op3(T1, T2, T3) -> handle_op(Rest, Line, Column, comp_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?and_op3(T1, T2, T3) -> handle_op(Rest, Line, Column, and_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?or_op3(T1, T2, T3) -> handle_op(Rest, Line, Column, or_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?arrow_op3(T1, T2, T3) -> handle_op(Rest, Line, Column, arrow_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); tokenize([T1, T2, T3|Rest], Line, Column, Scope, Tokens) when ?hat_op3(T1, T2, T3) -> handle_op(Rest, Line, Column, hat_op, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); % ## Containers + punctuation tokens tokenize([T, T|Rest], Line, Column, Scope, Tokens) when T == $<; T == $> -> Token = {list_to_atom([T, T]), {Line, Column, Column + 2}}, handle_terminator(Rest, Line, Column + 2, Scope, Token, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when T == $(; T == ${; T == $}; T == $[; T == $]; T == $); T == $, -> Token = {list_to_atom([T]), {Line, Column, Column + 1}}, handle_terminator(Rest, Line, Column + 1, Scope, Token, Tokens); % ## Two Token Operators tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?two_op(T1, T2) -> handle_op(Rest, Line, Column, two_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?arrow_op(T1, T2) -> handle_op(Rest, Line, Column, arrow_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?comp_op2(T1, T2) -> handle_op(Rest, Line, Column, comp_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?rel_op2(T1, T2) -> handle_op(Rest, Line, Column, rel_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?and_op(T1, T2) -> handle_op(Rest, Line, Column, and_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?or_op(T1, T2) -> handle_op(Rest, Line, Column, or_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?in_match_op(T1, T2) -> handle_op(Rest, Line, Column, in_match_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?type_op(T1, T2) -> handle_op(Rest, Line, Column, type_op, 2, list_to_atom([T1, T2]), Scope, Tokens); tokenize([T1, T2|Rest], Line, Column, Scope, Tokens) when ?stab_op(T1, T2) -> handle_op(Rest, Line, Column, stab_op, 2, list_to_atom([T1, T2]), Scope, Tokens); % ## Single Token Operators tokenize([T|Rest], Line, Column, Scope, Tokens) when ?at_op(T) -> handle_unary_op(Rest, Line, Column, at_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?capture_op(T) -> handle_unary_op(Rest, Line, Column, capture_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?unary_op(T) -> handle_unary_op(Rest, Line, Column, unary_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?rel_op(T) -> handle_op(Rest, Line, Column, rel_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?dual_op(T) -> handle_unary_op(Rest, Line, Column, dual_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?mult_op(T) -> handle_op(Rest, Line, Column, mult_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?match_op(T) -> handle_op(Rest, Line, Column, match_op, 1, list_to_atom([T]), Scope, Tokens); tokenize([T|Rest], Line, Column, Scope, Tokens) when ?pipe_op(T) -> handle_op(Rest, Line, Column, pipe_op, 1, list_to_atom([T]), Scope, Tokens); % Others tokenize([$%|T], Line, Column, Scope, Tokens) -> case strip_space(T, 0, Column + 1) of {[${|_] = Rest, Counter, Offset} -> tokenize(Rest, Line + Counter, Offset, Scope, [{'%{}', {Line, Column, Column + 1}}|Tokens]); {Rest, Counter, Offset} -> tokenize(Rest, Line + Counter, Offset, Scope, [{'%', {Line, Column, Column + 1}}|Tokens]) end; tokenize([$.|T], Line, Column, Scope, Tokens) -> {Rest, Counter, Offset} = strip_space(T, 0, Column + 1), handle_dot([$.|Rest], Line + Counter, Offset - 1, Column, Scope, Tokens); % Integers and floats tokenize([H|_] = String, Line, Column, Scope, Tokens) when ?is_digit(H) -> {Rest, Number, Length} = tokenize_number(String, [], false), tokenize(Rest, Line, Column + Length, Scope, [{number, {Line, Column, Column + Length}, Number}|Tokens]); % Identifiers (including aliases) tokenize([H|_] = Original, Line, Column, Scope, Tokens) when ?is_identifier_start(H) -> case tokenize_any_identifier(Original, Line, Scope) of {ok, Rest, Atom, Length, HasAt, HasEnding} -> case Rest of [$:|T] when ?is_space(hd(T)) -> tokenize(T, Line, Column + Length + 1, Scope, [{kw_identifier, {Line, Column, Column + Length + 1}, Atom}|Tokens]); [$:|T] when hd(T) /= $: -> String = atom_to_list(Atom) ++ [$:], Reason = {Line, "keyword argument must be followed by space after: ", String}, {error, Reason, Original, Tokens}; _ when HasAt -> Reason = {Line, invalid_character_error($@), atom_to_list(Atom)}, {error, Reason, Original, Tokens}; _ when ?is_upcase(H) -> tokenize_alias(Rest, Line, Column, Atom, Length, HasEnding, Scope, Tokens); _ -> tokenize_other_identifier(Rest, Line, Column, Length, Atom, Scope, Tokens) end; {error, Reason} -> {error, Reason, Original, Tokens} end; % Spaces tokenize([T|Rest], Line, Column, Scope, Tokens) when ?is_horizontal_space(T) -> case strip_horizontal_space(Rest) of {Remaining, Stripped} -> handle_space_sensitive_tokens(Remaining, Line, Column + 1 + Stripped, Scope, Tokens) end; tokenize([T|Rest] = Original, Line, _Column, _Scope, Tokens) when ?is_invalid_space(T) -> Message = io_lib:format("invalid space character U+~.16B before: ", [T]), {error, {Line, lists:flatten(Message), until_eol(Rest)}, Original, Tokens}; tokenize(T, Line, _Column, _Scope, Tokens) -> {error, {Line, "invalid token: ", until_eol(T)}, T, Tokens}. strip_horizontal_space(T) -> strip_horizontal_space(T, 0). strip_horizontal_space([H|T], Counter) when ?is_horizontal_space(H) -> strip_horizontal_space(T, Counter + 1); strip_horizontal_space(T, Counter) -> {T, Counter}. strip_space(T, Counter, Column) -> case strip_horizontal_space(T) of {"\r\n" ++ Rest, _} -> strip_space(Rest, Counter + 1, 1); {"\n" ++ Rest, _} -> strip_space(Rest, Counter + 1, 1); {Rest, Length} -> {Rest, Counter, Column + Length} end. until_eol("\r\n" ++ _) -> []; until_eol("\n" ++ _) -> []; until_eol([]) -> []; until_eol([H|T]) -> [H|until_eol(T)]. handle_char(7) -> {"\\a", "alert"}; handle_char($\b) -> {"\\b", "backspace"}; handle_char($\d) -> {"\\d", "delete"}; handle_char($\e) -> {"\\e", "escape"}; handle_char($\f) -> {"\\f", "form feed"}; handle_char($\n) -> {"\\n", "newline"}; handle_char($\r) -> {"\\r", "carriage return"}; handle_char($\s) -> {"\\s", "space"}; handle_char($\t) -> {"\\t", "tab"}; handle_char($\v) -> {"\\v", "vertical tab"}; handle_char(_) -> false. escape_char(List) -> <> = elixir_interpolation:unescape_chars(list_to_binary(List)), Char. %% Handlers handle_heredocs(T, Line, Column, H, Scope, Tokens) -> case extract_heredoc_with_interpolation(Line, Column, Scope, true, T, H) of {ok, NewLine, NewColumn, Parts, Rest} -> Token = {string_type(H), {Line, Column, NewColumn}, unescape_tokens(Parts)}, tokenize(Rest, NewLine, NewColumn, Scope, [Token|Tokens]); {error, Reason} -> {error, Reason, [H, H, H] ++ T, Tokens} end. handle_strings(T, Line, Column, H, Scope, Tokens) -> case elixir_interpolation:extract(Line, Column, Scope, true, T, H) of {error, Reason} -> interpolation_error(Reason, [H|T], Tokens, " (for string starting at line ~B)", [Line]); {NewLine, NewColumn, Parts, [$:|Rest]} when ?is_space(hd(Rest)) -> Unescaped = unescape_tokens(Parts), Key = case Scope#elixir_tokenizer.existing_atoms_only of true -> kw_identifier_safe; false -> kw_identifier_unsafe end, tokenize(Rest, NewLine, NewColumn, Scope, [{Key, {Line, Column - 1, NewColumn}, Unescaped}|Tokens]); {NewLine, NewColumn, Parts, Rest} -> Token = {string_type(H), {Line, Column - 1, NewColumn}, unescape_tokens(Parts)}, tokenize(Rest, NewLine, NewColumn, Scope, [Token|Tokens]) end. handle_unary_op([$:|Rest], Line, Column, _Kind, Length, Op, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + Length + 1, Scope, [{kw_identifier, {Line, Column, Column + Length}, Op}|Tokens]); handle_unary_op(Rest, Line, Column, Kind, Length, Op, Scope, Tokens) -> case strip_horizontal_space(Rest) of {[$/|_] = Remaining, Extra} -> tokenize(Remaining, Line, Column + Length + Extra, Scope, [{identifier, {Line, Column, Column + Length}, Op}|Tokens]); {Remaining, Extra} -> tokenize(Remaining, Line, Column + Length + Extra, Scope, [{Kind, {Line, Column, Column + Length}, Op}|Tokens]) end. handle_op([$:|Rest], Line, Column, _Kind, Length, Op, Scope, Tokens) when ?is_space(hd(Rest)) -> tokenize(Rest, Line, Column + Length + 1, Scope, [{kw_identifier, {Line, Column, Column + Length}, Op}|Tokens]); handle_op(Rest, Line, Column, Kind, Length, Op, Scope, Tokens) -> case strip_horizontal_space(Rest) of {[$/|_] = Remaining, Extra} -> tokenize(Remaining, Line, Column + Length + Extra, Scope, [{identifier, {Line, Column, Column + Length}, Op}|Tokens]); {Remaining, Extra} -> tokenize(Remaining, Line, Column + Length + Extra, Scope, add_token_with_nl({Kind, {Line, Column, Column + Length}, Op}, Tokens)) end. % ## Three Token Operators handle_dot([$., T1, T2, T3|Rest], Line, Column, DotColumn, Scope, Tokens) when ?unary_op3(T1, T2, T3); ?comp_op3(T1, T2, T3); ?and_op3(T1, T2, T3); ?or_op3(T1, T2, T3); ?arrow_op3(T1, T2, T3); ?hat_op3(T1, T2, T3) -> handle_call_identifier(Rest, Line, Column + 1, DotColumn, 3, list_to_atom([T1, T2, T3]), Scope, Tokens); % ## Two Token Operators handle_dot([$., T1, T2|Rest], Line, Column, DotColumn, Scope, Tokens) when ?comp_op2(T1, T2); ?rel_op2(T1, T2); ?and_op(T1, T2); ?or_op(T1, T2); ?arrow_op(T1, T2); ?in_match_op(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2); ?type_op(T1, T2) -> handle_call_identifier(Rest, Line, Column + 1, DotColumn, 2, list_to_atom([T1, T2]), Scope, Tokens); % ## Single Token Operators handle_dot([$., T|Rest], Line, Column, DotColumn, Scope, Tokens) when ?at_op(T); ?unary_op(T); ?capture_op(T); ?dual_op(T); ?mult_op(T); ?rel_op(T); ?match_op(T); ?pipe_op(T); T == $% -> handle_call_identifier(Rest, Line, Column + 1, DotColumn, 1, list_to_atom([T]), Scope, Tokens); % ## Exception for .( as it needs to be treated specially in the parser handle_dot([$., $(|Rest], Line, Column, DotColumn, Scope, Tokens) -> tokenize([$(|Rest], Line, Column + 2, Scope, add_token_with_nl({dot_call_op, {Line, DotColumn, DotColumn + 1}, '.'}, Tokens)); handle_dot([$., H|T] = Original, Line, Column, DotColumn, Scope, Tokens) when ?is_quote(H) -> case elixir_interpolation:extract(Line, Column + 2, Scope, true, T, H) of {NewLine, NewColumn, [Part], Rest} when is_binary(Part) -> case unsafe_to_atom(Part, Line, Scope) of {ok, Atom} -> Token = check_call_identifier(identifier, Line, Column, max(NewColumn - Column, 0), Atom, Rest), tokenize(Rest, NewLine, NewColumn, Scope, [Token|add_token_with_nl({'.', {Line, DotColumn, DotColumn + 1}}, Tokens)]); {error, Reason} -> {error, Reason, Original, Tokens} end; {error, Reason} -> interpolation_error(Reason, Original, Tokens, " (for function name starting at line ~B)", [Line]) end; handle_dot([$.|Rest], Line, Column, DotColumn, Scope, Tokens) -> tokenize(Rest, Line, Column + 1, Scope, add_token_with_nl({'.', {Line, DotColumn, DotColumn + 1}}, Tokens)). handle_call_identifier(Rest, Line, Column, DotColumn, Length, Op, Scope, Tokens) -> {_, {_, _, NewColumn}, _} = Token = check_call_identifier(identifier, Line, Column, Length, Op, Rest), tokenize(Rest, Line, NewColumn, Scope, [Token|add_token_with_nl({'.', {Line, DotColumn, DotColumn + 1}}, Tokens)]). % ## Ambiguous unary/binary operators tokens handle_space_sensitive_tokens([Sign, NotMarker|T], Line, Column, Scope, [{Identifier, _, _} = H|Tokens]) when ?dual_op(Sign), not(?is_space(NotMarker)), NotMarker /= $(, NotMarker /= $[, NotMarker /= $<, NotMarker /= ${, %% containers NotMarker /= $%, NotMarker /= $+, NotMarker /= $-, NotMarker /= $/, NotMarker /= $>, %% operators Identifier == identifier -> Rest = [NotMarker|T], tokenize(Rest, Line, Column + 1, Scope, [{dual_op, {Line, Column, Column + 1}, list_to_atom([Sign])}, setelement(1, H, op_identifier)|Tokens]); handle_space_sensitive_tokens(String, Line, Column, Scope, Tokens) -> tokenize(String, Line, Column, Scope, Tokens). %% Helpers eol(_Line, _Column, [{';', _}|_] = Tokens) -> Tokens; eol(_Line, _Column, [{',', _}|_] = Tokens) -> Tokens; eol(_Line, _Column, [{eol, _}|_] = Tokens) -> Tokens; eol(Line, Column, Tokens) -> [{eol, {Line, Column, Column + 1}}|Tokens]. unsafe_to_atom(Part, Line, #elixir_tokenizer{}) when is_binary(Part) andalso size(Part) > 255; is_list(Part) andalso length(Part) > 255 -> {error, {Line, "atom length must be less than system limit", ":"}}; unsafe_to_atom(Binary, _Line, #elixir_tokenizer{existing_atoms_only=true}) when is_binary(Binary) -> {ok, binary_to_existing_atom(Binary, utf8)}; unsafe_to_atom(Binary, _Line, #elixir_tokenizer{}) when is_binary(Binary) -> {ok, binary_to_atom(Binary, utf8)}; unsafe_to_atom(List, _Line, #elixir_tokenizer{existing_atoms_only=true}) when is_list(List) -> {ok, list_to_existing_atom(List)}; unsafe_to_atom(List, _Line, #elixir_tokenizer{}) when is_list(List) -> {ok, list_to_atom(List)}. collect_modifiers([H|T], Buffer) when ?is_downcase(H) or ?is_upcase(H) -> collect_modifiers(T, [H|Buffer]); collect_modifiers(Rest, Buffer) -> {Rest, lists:reverse(Buffer)}. %% Heredocs extract_heredoc_with_interpolation(Line, Column, Scope, Interpol, T, H) -> case extract_heredoc(Line, Column, T, H) of {ok, NewLine, NewColumn, Body, Rest} -> case elixir_interpolation:extract(Line + 1, 1, Scope, Interpol, Body, 0) of {error, Reason} -> {error, interpolation_format(Reason, " (for heredoc starting at line ~B)", [Line])}; {_, _, Parts, []} -> {ok, NewLine, NewColumn, Parts, Rest} end; {error, _} = Error -> Error end. extract_heredoc(Line0, Column0, Rest0, Marker) -> case extract_heredoc_header(Rest0) of {ok, Rest1} -> %% We prepend a new line so we can transparently remove %% spaces later. This new line is removed by calling `tl` %% in the final heredoc body three lines below. case extract_heredoc_body(Line0, Column0, Marker, [$\n|Rest1], []) of {ok, Line1, Body, Rest2, Spaces} -> {ok, Line1, 1, tl(remove_heredoc_spaces(Body, Spaces)), Rest2}; {error, ErrorLine} -> Terminator = [Marker, Marker, Marker], Message = "missing terminator: ~ts (for heredoc starting at line ~B)", {error, {ErrorLine, io_lib:format(Message, [Terminator, Line0]), []}} end; error -> Message = "heredoc start must be followed by a new line after ", {error, {Line0, io_lib:format(Message, []), [Marker, Marker, Marker]}} end. %% Remove spaces from heredoc based on the position of the final quotes. remove_heredoc_spaces(Body, 0) -> lists:reverse([0|Body]); remove_heredoc_spaces(Body, Spaces) -> remove_heredoc_spaces([0|Body], [], Spaces, Spaces). remove_heredoc_spaces([H, $\n|T], [Backtrack|Buffer], Spaces, Original) when Spaces > 0, ?is_horizontal_space(H) -> remove_heredoc_spaces([Backtrack, $\n|T], Buffer, Spaces - 1, Original); remove_heredoc_spaces([$\n=H|T], Buffer, _Spaces, Original) -> remove_heredoc_spaces(T, [H|Buffer], Original, Original); remove_heredoc_spaces([H|T], Buffer, Spaces, Original) -> remove_heredoc_spaces(T, [H|Buffer], Spaces, Original); remove_heredoc_spaces([], Buffer, _Spaces, _Original) -> Buffer. %% Extract the heredoc header. extract_heredoc_header("\r\n" ++ Rest) -> {ok, Rest}; extract_heredoc_header("\n" ++ Rest) -> {ok, Rest}; extract_heredoc_header([H|T]) when ?is_horizontal_space(H) -> extract_heredoc_header(T); extract_heredoc_header(_) -> error. %% Extract heredoc body. It returns the heredoc body (in reverse order), %% the remaining of the document and the number of spaces the heredoc %% is aligned. extract_heredoc_body(Line, _Column, Marker, Rest, Buffer) -> case extract_heredoc_line(Marker, Rest, Buffer, 0) of {ok, NewBuffer, NewRest} -> extract_heredoc_body(Line + 1, 1, Marker, NewRest, NewBuffer); {ok, NewBuffer, NewRest, Spaces} -> {ok, Line, NewBuffer, NewRest, Spaces}; {error, eof} -> {error, Line} end. %% Extract a line from the heredoc prepending its contents to a buffer. extract_heredoc_line("\r\n" ++ Rest, Buffer) -> {ok, [$\n|Buffer], Rest}; extract_heredoc_line("\n" ++ Rest, Buffer) -> {ok, [$\n|Buffer], Rest}; extract_heredoc_line([H|T], Buffer) -> extract_heredoc_line(T, [H|Buffer]); extract_heredoc_line(_, _) -> {error, eof}. %% Extract each heredoc line trying to find a match according to the marker. extract_heredoc_line(Marker, [H|T], Buffer, Counter) when ?is_horizontal_space(H) -> extract_heredoc_line(Marker, T, [H|Buffer], Counter + 1); extract_heredoc_line(Marker, [Marker, Marker, Marker|T], Buffer, Counter) -> {ok, Buffer, T, Counter}; extract_heredoc_line(_Marker, Rest, Buffer, _Counter) -> extract_heredoc_line(Rest, Buffer). %% Integers and floats %% At this point, we are at least sure the first digit is a number. %% Check if we have a point followed by a number; tokenize_number([$., H|T], Acc, false) when ?is_digit(H) -> tokenize_number(T, [H, $.|Acc], true); %% Check if we have an underscore followed by a number; tokenize_number([$_, H|T], Acc, Bool) when ?is_digit(H) -> tokenize_number(T, [H|Acc], Bool); %% Check if we have e- followed by numbers (valid only for floats); tokenize_number([E, S, H|T], Acc, true) when (E == $E) or (E == $e), ?is_digit(H), S == $+ orelse S == $- -> tokenize_number(T, [H, S, $e|Acc], true); %% Check if we have e followed by numbers (valid only for floats); tokenize_number([E, H|T], Acc, true) when (E == $E) or (E == $e), ?is_digit(H) -> tokenize_number(T, [H, $e|Acc], true); %% Finally just numbers. tokenize_number([H|T], Acc, Bool) when ?is_digit(H) -> tokenize_number(T, [H|Acc], Bool); %% Cast to float... tokenize_number(Rest, Acc, true) -> {Rest, list_to_float(lists:reverse(Acc)), length(Acc)}; %% Or integer. tokenize_number(Rest, Acc, false) -> {Rest, list_to_integer(lists:reverse(Acc)), length(Acc)}. tokenize_hex([H|T], Acc) when ?is_hex(H) -> tokenize_hex(T, [H|Acc]); tokenize_hex([$_, H|T], Acc) when ?is_hex(H) -> tokenize_hex(T, [H|Acc]); tokenize_hex(Rest, Acc) -> {Rest, list_to_integer(lists:reverse(Acc), 16), length(Acc)}. tokenize_octal([H|T], Acc) when ?is_octal(H) -> tokenize_octal(T, [H|Acc]); tokenize_octal([$_, H|T], Acc) when ?is_octal(H) -> tokenize_octal(T, [H|Acc]); tokenize_octal(Rest, Acc) -> {Rest, list_to_integer(lists:reverse(Acc), 8), length(Acc)}. tokenize_bin([H|T], Acc) when ?is_bin(H) -> tokenize_bin(T, [H|Acc]); tokenize_bin([$_, H|T], Acc) when ?is_bin(H) -> tokenize_bin(T, [H|Acc]); tokenize_bin(Rest, Acc) -> {Rest, list_to_integer(lists:reverse(Acc), 2), length(Acc)}. %% Comments tokenize_comment("\r\n" ++ _ = Rest) -> Rest; tokenize_comment("\n" ++ _ = Rest) -> Rest; tokenize_comment([_|Rest]) -> tokenize_comment(Rest); tokenize_comment([]) -> []. %% Atoms %% Handle atoms specially since they support @ tokenize_atom(T, Acc) -> tokenize_atom(T, Acc, 0). tokenize_atom([H|T], Acc, Length) when ?is_atom(H) -> tokenize_atom(T, [H|Acc], Length + 1); tokenize_atom([H|T], Acc, Length) when H == $?; H == $! -> {T, lists:reverse([H|Acc]), Length + 1}; tokenize_atom(Rest, Acc, Length) -> {Rest, lists:reverse(Acc), Length}. %% Identifiers %% At this point, the validity of the first character was already verified. tokenize_any_base_identifier(Original) -> tokenize_any_base_identifier(Original, [], false). tokenize_any_base_identifier([H|T], Acc, HasAt) when ?is_atom(H) -> tokenize_any_base_identifier(T, [H|Acc], HasAt orelse H == $@); tokenize_any_base_identifier(Rest, Acc, HasAt) -> {Rest, lists:reverse(Acc), length(Acc), HasAt}. %% Tokenize any identifier, handling kv, punctuated, paren, bracket and do identifiers. tokenize_any_identifier(Original, Line, Scope) -> {Rest, Identifier, Length, HasAt} = tokenize_any_base_identifier(Original), {AllIdentifier, AllRest, AllLength, HasEnding} = case Rest of [H|T] when H == $?; H == $! -> {Identifier ++ [H], T, Length + 1, true}; _ -> {Identifier, Rest, Length, false} end, case unsafe_to_atom(AllIdentifier, Line, Scope) of {ok, Atom} -> {ok, AllRest, Atom, AllLength, HasAt, HasEnding}; {error, Reason} -> {error, Reason} end. tokenize_alias(Rest, Line, Column, Atom, Length, HasEnding, Scope, Tokens) -> case HasEnding of true -> AtomName = atom_to_list(Atom), Ending = lists:last(AtomName), Reason = {Line, invalid_character_error(Ending), AtomName}, {error, Reason, AtomName, Tokens}; _ -> tokenize(Rest, Line, Column + Length, Scope, [{aliases, {Line, Column, Column + Length}, [Atom]}|Tokens]) end. tokenize_other_identifier(Rest, Line, Column, Length, Atom, Scope, Tokens) -> case tokenize_kw_or_other(Rest, identifier, Line, Column, Length, Atom, Tokens) of {keyword, Rest, {_, {_, _, EndColumn}} = Check, T} -> handle_terminator(Rest, Line, EndColumn, Scope, Check, T); {keyword, Rest, {_, {_, _, EndColumn}, _} = Check, T} -> handle_terminator(Rest, Line, EndColumn, Scope, Check, T); {identifier, Rest, {_, {_, _, EndColumn}, _} = Token} -> tokenize(Rest, Line, EndColumn, Scope, [Token|Tokens]); {error, _, _, _} = Error -> Error end. tokenize_kw_or_other(Rest, Kind, Line, Column, Length, Atom, Tokens) -> case check_keyword(Line, Column, Length, Atom, Tokens) of nomatch -> {identifier, Rest, check_call_identifier(Kind, Line, Column, Length, Atom, Rest)}; {ok, [Check|T]} -> {keyword, Rest, Check, T}; {error, Token} -> {error, {Line, "syntax error before: ", Token}, atom_to_list(Atom) ++ Rest, Tokens} end. %% Check if it is a call identifier (paren | bracket | do) check_call_identifier(_Kind, Line, Column, Length, Atom, [$(|_]) -> {paren_identifier, {Line, Column, Column + Length}, Atom}; check_call_identifier(_Kind, Line, Column, Length, Atom, [$[|_]) -> {bracket_identifier, {Line, Column, Column + Length}, Atom}; check_call_identifier(Kind, Line, Column, Length, Atom, _Rest) -> {Kind, {Line, Column, Column + Length}, Atom}. add_token_with_nl(Left, [{eol, _}|T]) -> [Left|T]; add_token_with_nl(Left, T) -> [Left|T]. %% Error handling interpolation_error(Reason, Rest, Tokens, Extension, Args) -> {error, interpolation_format(Reason, Extension, Args), Rest, Tokens}. interpolation_format({string, Line, Message, Token}, Extension, Args) -> {Line, io_lib:format("~ts" ++ Extension, [Message|Args]), Token}; interpolation_format({_, _, _} = Reason, _Extension, _Args) -> Reason. %% Terminators handle_terminator(Rest, Line, Column, Scope, Token, Tokens) -> case handle_terminator(Token, Scope) of {error, Reason} -> {error, Reason, atom_to_list(element(1, Token)) ++ Rest, Tokens}; New -> tokenize(Rest, Line, Column, New, [Token|Tokens]) end. handle_terminator(_, #elixir_tokenizer{check_terminators=false} = Scope) -> Scope; handle_terminator(Token, #elixir_tokenizer{terminators=Terminators} = Scope) -> case check_terminator(Token, Terminators) of {error, _} = Error -> Error; New -> Scope#elixir_tokenizer{terminators=New} end. check_terminator({S, Line}, Terminators) when S == 'fn' -> [{fn, Line}|Terminators]; check_terminator({S, _} = New, Terminators) when S == 'do'; S == '('; S == '['; S == '{'; S == '<<' -> [New|Terminators]; check_terminator({E, _}, [{S, _}|Terminators]) when S == 'do', E == 'end'; S == 'fn', E == 'end'; S == '(', E == ')'; S == '[', E == ']'; S == '{', E == '}'; S == '<<', E == '>>' -> Terminators; check_terminator({E, {Line, _, _}}, [{Start, {StartLine, _, _}}|_]) when E == 'end'; E == ')'; E == ']'; E == '}'; E == '>>' -> End = terminator(Start), MessagePrefix = "unexpected token: \"", MessageSuffix = io_lib:format("\". \"~ts\" starting at line ~B is missing terminator \"~ts\"", [Start, StartLine, End]), {error, {Line, {MessagePrefix, MessageSuffix}, [atom_to_list(E)]}}; check_terminator({E, Line}, []) when E == 'end'; E == ')'; E == ']'; E == '}'; E == '>>' -> {error, {Line, "unexpected token: ", atom_to_list(E)}}; check_terminator(_, Terminators) -> Terminators. string_type($") -> bin_string; string_type($') -> list_string. sigil_terminator($() -> $); sigil_terminator($[) -> $]; sigil_terminator(${) -> $}; sigil_terminator($<) -> $>; sigil_terminator(O) -> O. terminator('fn') -> 'end'; terminator('do') -> 'end'; terminator('(') -> ')'; terminator('[') -> ']'; terminator('{') -> '}'; terminator('<<') -> '>>'. %% Keywords checking check_keyword(_Line, _Column, _Length, _Atom, [{'.', _}|_]) -> nomatch; check_keyword(DoLine, DoColumn, _Length, do, [{Identifier, {Line, Column, EndColumn}, Atom}|T]) when Identifier == identifier -> {ok, add_token_with_nl({do, {DoLine, DoColumn, DoColumn + 2}}, [{do_identifier, {Line, Column, EndColumn}, Atom}|T])}; check_keyword(Line, Column, _Length, do, Tokens) -> case do_keyword_valid(Tokens) of true -> {ok, add_token_with_nl({do, {Line, Column, Column + 2}}, Tokens)}; false -> {error, "do"} end; check_keyword(Line, Column, Length, Atom, Tokens) -> case keyword(Atom) of false -> nomatch; token -> {ok, [{Atom, {Line, Column, Column + Length}}|Tokens]}; block -> {ok, [{block_identifier, {Line, Column, Column + Length}, Atom}|Tokens]}; unary_op -> {ok, [{unary_op, {Line, Column, Column + Length}, Atom}|Tokens]}; Kind -> {ok, add_token_with_nl({Kind, {Line, Column, Column + Length}, Atom}, Tokens)} end. %% do is only valid after the end, true, false and nil keywords do_keyword_valid([{Atom, _}|_]) -> case Atom of 'end' -> true; nil -> true; true -> true; false -> true; _ -> keyword(Atom) == false end; do_keyword_valid(_) -> true. % Regular keywords keyword('fn') -> token; keyword('end') -> token; keyword('true') -> token; keyword('false') -> token; keyword('nil') -> token; % Operators keywords keyword('not') -> unary_op; keyword('and') -> and_op; keyword('or') -> or_op; keyword('when') -> when_op; keyword('in') -> in_op; % Block keywords keyword('after') -> block; keyword('else') -> block; keyword('rescue') -> block; keyword('catch') -> block; keyword(_) -> false. invalid_character_error(Char) -> "invalid character '" ++ [Char] ++ "' in identifier: ". elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_translator.erl000066400000000000000000000354041254730255300242250ustar00rootroot00000000000000%% Translate Elixir quoted expressions to Erlang Abstract Format. %% Expects the tree to be expanded. -module(elixir_translator). -export([translate/2, translate_arg/3, translate_args/2, translate_block/3]). -import(elixir_scope, [mergev/2, mergec/2]). -import(elixir_errors, [compile_error/3, compile_error/4]). -include("elixir.hrl"). %% = translate({'=', Meta, [Left, Right]}, S) -> Return = case Left of {'_', _, Atom} when is_atom(Atom) -> S#elixir_scope.return; _ -> true end, {TRight, SR} = translate_block(Right, Return, S), {TLeft, SL} = elixir_clauses:match(fun translate/2, Left, SR), {{match, ?line(Meta), TLeft, TRight}, SL}; %% Containers translate({'{}', Meta, Args}, S) when is_list(Args) -> {TArgs, SE} = translate_args(Args, S), {{tuple, ?line(Meta), TArgs}, SE}; translate({'%{}', Meta, Args}, S) when is_list(Args) -> elixir_map:translate_map(Meta, Args, S); translate({'%', Meta, [Left, Right]}, S) -> elixir_map:translate_struct(Meta, Left, Right, S); translate({'<<>>', Meta, Args}, S) when is_list(Args) -> elixir_bitstring:translate(Meta, Args, S); %% Blocks translate({'__block__', Meta, Args}, #elixir_scope{return=Return} = S) when is_list(Args) -> {TArgs, SA} = translate_block(Args, [], Return, S#elixir_scope{return=true}), {{block, ?line(Meta), TArgs}, SA}; %% Erlang op translate({'__op__', Meta, [Op, Expr]}, S) when is_atom(Op) -> {TExpr, NS} = translate(Expr, S), {{op, ?line(Meta), Op, TExpr}, NS}; translate({'__op__', Meta, [Op, Left, Right]}, S) when is_atom(Op) -> {[TLeft, TRight], NS} = translate_args([Left, Right], S), {{op, ?line(Meta), Op, TLeft, TRight}, NS}; %% Lexical translate({Lexical, _, [_, _]}, S) when Lexical == import; Lexical == alias; Lexical == require -> {{atom, 0, nil}, S}; %% Pseudo variables translate({'__CALLER__', Meta, Atom}, S) when is_atom(Atom) -> {{var, ?line(Meta), '__CALLER__'}, S#elixir_scope{caller=true}}; %% Functions translate({'&', Meta, [{'/', [], [{Fun, [], Atom}, Arity]}]}, S) when is_atom(Fun), is_atom(Atom), is_integer(Arity) -> {{'fun', ?line(Meta), {function, Fun, Arity}}, S}; translate({'&', Meta, [Arg]}, S) when is_integer(Arg) -> compile_error(Meta, S#elixir_scope.file, "unhandled &~B outside of a capture", [Arg]); translate({fn, Meta, Clauses}, S) -> elixir_fn:translate(Meta, Clauses, S); %% Cond translate({'cond', CondMeta, [[{do, Pairs}]]}, S) -> [{'->', Meta, [[Condition], Body]}|T] = lists:reverse(Pairs), Case = case Condition of {'_', _, Atom} when is_atom(Atom) -> compile_error(Meta, S#elixir_scope.file, "unbound variable _ inside cond. " "If you want the last clause to always match, you probably meant to use: true ->"); X when is_atom(X) and (X /= false) and (X /= nil) -> build_cond_clauses(T, Body, Meta); _ -> {Truthy, Other} = build_truthy_clause(Meta, Condition, Body), Error = {{'.', Meta, [erlang, error]}, [], [cond_clause]}, Falsy = {'->', Meta, [[Other], Error]}, Acc = {'case', Meta, [Condition, [{do, [Truthy, Falsy]}]]}, build_cond_clauses(T, Acc, Meta) end, translate(replace_case_meta(CondMeta, Case), S); %% Case translate({'case', Meta, [Expr, KV]}, #elixir_scope{return=Return} = RS) -> S = RS#elixir_scope{return=true}, Clauses = elixir_clauses:get_pairs(do, KV, match), {TExpr, NS} = translate(Expr, S), {TClauses, TS} = elixir_clauses:clauses(Meta, Clauses, Return, NS), {{'case', ?line(Meta), TExpr, TClauses}, TS}; %% Try translate({'try', Meta, [Clauses]}, #elixir_scope{return=Return} = RS) -> S = RS#elixir_scope{noname=true, return=true}, Do = proplists:get_value('do', Clauses, nil), {TDo, SB} = elixir_translator:translate(Do, S), Catch = [Tuple || {X, _} = Tuple <- Clauses, X == 'rescue' orelse X == 'catch'], {TCatch, SC} = elixir_try:clauses(Meta, Catch, Return, mergec(S, SB)), case lists:keyfind('after', 1, Clauses) of {'after', After} -> {TBlock, SA} = translate(After, mergec(S, SC)), TAfter = unblock(TBlock); false -> {TAfter, SA} = {[], mergec(S, SC)} end, Else = elixir_clauses:get_pairs(else, Clauses, match), {TElse, SE} = elixir_clauses:clauses(Meta, Else, Return, mergec(S, SA)), SF = (mergec(S, SE))#elixir_scope{noname=RS#elixir_scope.noname}, {{'try', ?line(Meta), unblock(TDo), TElse, TCatch, TAfter}, SF}; %% Receive translate({'receive', Meta, [KV]}, #elixir_scope{return=Return} = RS) -> S = RS#elixir_scope{return=true}, Do = elixir_clauses:get_pairs(do, KV, match, true), case lists:keyfind('after', 1, KV) of false -> {TClauses, SC} = elixir_clauses:clauses(Meta, Do, Return, S), {{'receive', ?line(Meta), TClauses}, SC}; _ -> After = elixir_clauses:get_pairs('after', KV, expr), {TClauses, SC} = elixir_clauses:clauses(Meta, Do ++ After, Return, S), {FClauses, TAfter} = elixir_utils:split_last(TClauses), {_, _, [FExpr], _, FAfter} = TAfter, {{'receive', ?line(Meta), FClauses, FExpr, FAfter}, SC} end; %% Comprehensions translate({for, Meta, [_|_] = Args}, S) -> elixir_for:translate(Meta, Args, S); %% Super translate({super, Meta, Args}, S) when is_list(Args) -> Module = assert_module_scope(Meta, super, S), Function = assert_function_scope(Meta, super, S), elixir_def_overridable:ensure_defined(Meta, Module, Function, S), {_, Arity} = Function, {TArgs, TS} = if length(Args) == Arity -> translate_args(Args, S); true -> compile_error(Meta, S#elixir_scope.file, "super must be called with the same number of " "arguments as the current function") end, Super = elixir_def_overridable:name(Module, Function), {{call, ?line(Meta), {atom, ?line(Meta), Super}, TArgs}, TS#elixir_scope{super=true}}; %% Variables translate({'^', Meta, [{Name, VarMeta, Kind}]}, #elixir_scope{context=match} = S) when is_atom(Name), is_atom(Kind) -> Tuple = {Name, var_kind(VarMeta, Kind)}, case orddict:find(Tuple, S#elixir_scope.backup_vars) of {ok, {Value, _Counter}} -> {{var, ?line(Meta), Value}, S}; error -> compile_error(Meta, S#elixir_scope.file, "unbound variable ^~ts", [Name]) end; translate({'_', Meta, Kind}, #elixir_scope{context=match} = S) when is_atom(Kind) -> {{var, ?line(Meta), '_'}, S}; translate({'_', Meta, Kind}, S) when is_atom(Kind) -> compile_error(Meta, S#elixir_scope.file, "unbound variable _"); translate({Name, Meta, Kind}, #elixir_scope{extra=map_key} = S) when is_atom(Name), is_atom(Kind) -> compile_error(Meta, S#elixir_scope.file, "illegal use of variable ~ts in map key", [Name]); translate({Name, Meta, Kind}, S) when is_atom(Name), is_atom(Kind) -> elixir_scope:translate_var(Meta, Name, var_kind(Meta, Kind), S); %% Local calls translate({Name, Meta, Args}, S) when is_atom(Name), is_list(Meta), is_list(Args) -> if S#elixir_scope.context == match -> compile_error(Meta, S#elixir_scope.file, "cannot invoke local ~ts/~B inside match", [Name, length(Args)]); S#elixir_scope.context == guard -> Arity = length(Args), File = S#elixir_scope.file, case Arity of 0 -> compile_error(Meta, File, "unknown variable ~ts or cannot invoke " "local ~ts/~B inside guard", [Name, Name, Arity]); _ -> compile_error(Meta, File, "cannot invoke local ~ts/~B inside guard", [Name, Arity]) end; true -> Line = ?line(Meta), {TArgs, NS} = translate_args(Args, S), {{call, Line, {atom, Line, Name}, TArgs}, NS} end; %% Remote calls translate({{'.', _, [Left, Right]}, Meta, Args}, S) when (is_tuple(Left) orelse is_atom(Left)), is_atom(Right), is_list(Meta), is_list(Args) -> {TLeft, SL} = translate(Left, S), {TArgs, SA} = translate_args(Args, mergec(S, SL)), Line = ?line(Meta), Arity = length(Args), TRight = {atom, Line, Right}, %% We need to rewrite erlang function calls as operators %% because erl_eval chokes on them. We can remove this %% once a fix is merged into Erlang, keeping only the %% list operators one (since it is required for inlining %% [1, 2, 3] ++ Right in matches). case (Left == erlang) andalso erl_op(Right, Arity) of true -> {list_to_tuple([op, Line, Right] ++ TArgs), mergev(SL, SA)}; false -> assert_allowed_in_context(Meta, Left, Right, Arity, S), SC = mergev(SL, SA), case not is_atom(Left) andalso (Arity == 0) of true -> {Var, _, SV} = elixir_scope:build_var('_', SC), TVar = {var, Line, Var}, TMap = {map, Line, [ {map_field_assoc, Line, {atom, Line, '__struct__'}, {atom, Line, 'Elixir.KeyError'}}, {map_field_assoc, Line, {atom, Line, '__exception__'}, {atom, Line, 'true'}}, {map_field_assoc, Line, {atom, Line, key}, TRight}, {map_field_assoc, Line, {atom, Line, term}, TVar}]}, %% TODO There is a bug in dialyzer that makes it fail on %% empty maps. We work around the bug below by using %% the is_map/1 guard instead of matching on map. Hopefully %% we can use a match on 17.1. %% %% In the future, we could also use maps:get/2 instead %% of pattern match, reducing the AST footprint. %% %% http://erlang.org/pipermail/erlang-bugs/2014-April/004338.html {{'case', -1, TLeft, [ {clause, -1, [{map, Line, [{map_field_exact, Line, TRight, TVar}]}], [], [TVar]}, {clause, -1, [TVar], [[elixir_utils:erl_call(Line, erlang, is_map, [TVar])]], [elixir_utils:erl_call(Line, erlang, error, [TMap])]}, {clause, -1, [TVar], [], [{call, Line, {remote, Line, TVar, TRight}, []}]} ]}, SV}; false -> {{call, Line, {remote, Line, TLeft, TRight}, TArgs}, SC} end end; %% Anonymous function calls translate({{'.', _, [Expr]}, Meta, Args}, S) when is_list(Args) -> {TExpr, SE} = translate(Expr, S), {TArgs, SA} = translate_args(Args, mergec(S, SE)), {{call, ?line(Meta), TExpr, TArgs}, mergev(SE, SA)}; %% Literals translate(List, S) when is_list(List) -> Fun = case S#elixir_scope.context of match -> fun translate/2; _ -> fun(X, Acc) -> translate_arg(X, Acc, S) end end, translate_list(List, Fun, S, []); translate({Left, Right}, S) -> {TArgs, SE} = translate_args([Left, Right], S), {{tuple, 0, TArgs}, SE}; translate(Other, S) -> {elixir_utils:elixir_to_erl(Other), S}. %% Helpers erl_op(Op, Arity) -> erl_internal:list_op(Op, Arity) orelse erl_internal:comp_op(Op, Arity) orelse erl_internal:bool_op(Op, Arity) orelse erl_internal:arith_op(Op, Arity). translate_list([{'|', _, [_, _]=Args}], Fun, Acc, List) -> {[TLeft, TRight], TAcc} = lists:mapfoldl(Fun, Acc, Args), {build_list([TLeft|List], TRight), TAcc}; translate_list([H|T], Fun, Acc, List) -> {TH, TAcc} = Fun(H, Acc), translate_list(T, Fun, TAcc, [TH|List]); translate_list([], _Fun, Acc, List) -> {build_list(List, {nil, 0}), Acc}. build_list([H|T], Acc) -> build_list(T, {cons, 0, H, Acc}); build_list([], Acc) -> Acc. var_kind(Meta, Kind) -> case lists:keyfind(counter, 1, Meta) of {counter, Counter} -> Counter; false -> Kind end. %% Pack a list of expressions from a block. unblock({'block', _, Exprs}) -> Exprs; unblock(Expr) -> [Expr]. %% Translate args translate_arg(Arg, Acc, S) when is_number(Arg); is_atom(Arg); is_binary(Arg); is_pid(Arg); is_function(Arg) -> {TArg, _} = translate(Arg, S), {TArg, Acc}; translate_arg(Arg, Acc, S) -> {TArg, TAcc} = translate(Arg, mergec(S, Acc)), {TArg, mergev(Acc, TAcc)}. translate_args(Args, #elixir_scope{context=match} = S) -> lists:mapfoldl(fun translate/2, S, Args); translate_args(Args, S) -> lists:mapfoldl(fun(X, Acc) -> translate_arg(X, Acc, S) end, S, Args). %% Translate blocks translate_block([], Acc, _Return, S) -> {lists:reverse(Acc), S}; translate_block([H], Acc, Return, S) -> {TH, TS} = translate_block(H, Return, S), translate_block([], [TH|Acc], Return, TS); translate_block([H|T], Acc, Return, S) -> {TH, TS} = translate_block(H, false, S), translate_block(T, [TH|Acc], Return, TS). translate_block(Expr, Return, S) -> case (Return == false) andalso handles_no_return(Expr) of true -> translate(Expr, S#elixir_scope{return=Return}); false -> translate(Expr, S) end. %% return is typically true, except when we find one %% of the expressions below, which may handle return=false %% but must always return return=true. handles_no_return({'try', _, [_]}) -> true; handles_no_return({'cond', _, [_]}) -> true; handles_no_return({'for', _, [_|_]}) -> true; handles_no_return({'case', _, [_, _]}) -> true; handles_no_return({'receive', _, [_]}) -> true; handles_no_return({'__block__', _, [_|_]}) -> true; handles_no_return(_) -> false. %% Cond build_cond_clauses([{'->', NewMeta, [[Condition], Body]}|T], Acc, OldMeta) -> {Truthy, Other} = build_truthy_clause(NewMeta, Condition, Body), Falsy = {'->', OldMeta, [[Other], Acc]}, Case = {'case', NewMeta, [Condition, [{do, [Truthy, Falsy]}]]}, build_cond_clauses(T, Case, NewMeta); build_cond_clauses([], Acc, _) -> Acc. replace_case_meta(Meta, {'case', _, Args}) -> {'case', Meta, Args}; replace_case_meta(_Meta, Other) -> Other. build_truthy_clause(Meta, Condition, Body) -> case elixir_utils:returns_boolean(Condition) of true -> {{'->', Meta, [[true], Body]}, false}; false -> Var = {'cond', [], 'Elixir'}, Head = {'when', [], [Var, {'__op__', [], [ 'andalso', {{'.', [], [erlang, '/=']}, [], [Var, nil]}, {{'.', [], [erlang, '/=']}, [], [Var, false]} ]} ]}, {{'->', Meta, [[Head], Body]}, {'_', [], nil}} end. %% Assertions assert_module_scope(Meta, Kind, #elixir_scope{module=nil, file=File}) -> compile_error(Meta, File, "cannot invoke ~ts outside module", [Kind]); assert_module_scope(_Meta, _Kind, #elixir_scope{module=Module}) -> Module. assert_function_scope(Meta, Kind, #elixir_scope{function=nil, file=File}) -> compile_error(Meta, File, "cannot invoke ~ts outside function", [Kind]); assert_function_scope(_Meta, _Kind, #elixir_scope{function=Function}) -> Function. assert_allowed_in_context(Meta, Left, Right, Arity, #elixir_scope{context=Context} = S) when (Context == match) orelse (Context == guard) -> case (Left == erlang) andalso erl_internal:guard_bif(Right, Arity) of true -> ok; false -> compile_error(Meta, S#elixir_scope.file, "cannot invoke remote function ~ts.~ts/~B inside ~ts", ['Elixir.Macro':to_string(Left), Right, Arity, Context]) end; assert_allowed_in_context(_, _, _, _, _) -> ok. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_try.erl000066400000000000000000000153001254730255300226430ustar00rootroot00000000000000-module(elixir_try). -export([clauses/4]). -include("elixir.hrl"). clauses(_Meta, Clauses, Return, S) -> Catch = elixir_clauses:get_pairs('catch', Clauses, 'catch'), Rescue = elixir_clauses:get_pairs(rescue, Clauses, rescue), reduce_clauses(Rescue ++ Catch, [], S, Return, S). reduce_clauses([H|T], Acc, SAcc, Return, S) -> {TH, TS} = each_clause(H, Return, SAcc), reduce_clauses(T, TH ++ Acc, elixir_scope:mergec(S, TS), Return, S); reduce_clauses([], Acc, SAcc, _Return, _S) -> {lists:reverse(Acc), SAcc}. each_clause({'catch', Meta, Raw, Expr}, Return, S) -> {Args, Guards} = elixir_clauses:extract_splat_guards(Raw), Final = case Args of [X] -> [throw, X, {'_', Meta, nil}]; [X, Y] -> [X, Y, {'_', Meta, nil}] end, Condition = [{'{}', Meta, Final}], {TC, TS} = elixir_clauses:clause(?line(Meta), fun elixir_translator:translate_args/2, Condition, Expr, Guards, Return, S), {[TC], TS}; each_clause({rescue, Meta, [{in, _, [Left, Right]}], Expr}, Return, S) -> {VarName, _, CS} = elixir_scope:build_var('_', S), Var = {VarName, Meta, nil}, {Parts, Safe, FS} = rescue_guards(Meta, Var, Right, CS), Body = case Left of {'_', _, Atom} when is_atom(Atom) -> Expr; _ -> Normalized = case Safe of true -> Var; false -> {{'.', Meta, ['Elixir.Exception', normalize]}, Meta, [error, Var]} end, prepend_to_block(Meta, {'=', Meta, [Left, Normalized]}, Expr) end, build_rescue(Meta, Parts, Body, Return, FS); each_clause({rescue, Meta, _, _}, _Return, S) -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "invalid arguments for rescue in try"); each_clause({Key, Meta, _, _}, _Return, S) -> elixir_errors:compile_error(Meta, S#elixir_scope.file, "invalid key ~ts in try", [Key]). %% Helpers build_rescue(Meta, Parts, Body, Return, S) -> Matches = [Match || {Match, _} <- Parts], {{clause, Line, TMatches, _, TBody}, TS} = elixir_clauses:clause(?line(Meta), fun elixir_translator:translate_args/2, Matches, Body, [], Return, S), TClauses = [begin TArgs = [{tuple, Line, [{atom, Line, error}, TMatch, {var, Line, '_'}]}], TGuards = elixir_clauses:guards(Line, Guards, [], TS), {clause, Line, TArgs, TGuards, TBody} end || {TMatch, {_, Guards}} <- lists:zip(TMatches, Parts)], {TClauses, TS}. %% Convert rescue clauses into guards. rescue_guards(_, Var, {'_', _, _}, S) -> {[{Var, []}], false, S}; rescue_guards(Meta, Var, Aliases, S) -> {Elixir, Erlang} = rescue_each_ref(Meta, Var, Aliases, [], [], S), {ElixirParts, ES} = case Elixir of [] -> {[], S}; _ -> {VarName, _, CS} = elixir_scope:build_var('_', S), StructVar = {VarName, Meta, nil}, Map = {'%{}', Meta, [{'__struct__', StructVar}, {'__exception__', true}]}, Match = {'=', Meta, [Map, Var]}, Guards = [{erl(Meta, '=='), Meta, [StructVar, Mod]} || Mod <- Elixir], {[{Match, Guards}], CS} end, ErlangParts = case Erlang of [] -> []; _ -> [{Var, Erlang}] end, {ElixirParts ++ ErlangParts, ErlangParts == [], ES}. %% Rescue each atom name considering their Erlang or Elixir matches. %% Matching of variables is done with Erlang exceptions is done in %% function for optimization. rescue_each_ref(Meta, Var, [H|T], Elixir, Erlang, S) when is_atom(H) -> case erl_rescue_guard_for(Meta, Var, H) of false -> rescue_each_ref(Meta, Var, T, [H|Elixir], Erlang, S); Expr -> rescue_each_ref(Meta, Var, T, [H|Elixir], [Expr|Erlang], S) end; rescue_each_ref(_, _, [], Elixir, Erlang, _) -> {Elixir, Erlang}. %% Handle erlang rescue matches. erl_rescue_guard_for(Meta, Var, 'Elixir.UndefinedFunctionError') -> {erl(Meta, '=='), Meta, [Var, undef]}; erl_rescue_guard_for(Meta, Var, 'Elixir.FunctionClauseError') -> {erl(Meta, '=='), Meta, [Var, function_clause]}; erl_rescue_guard_for(Meta, Var, 'Elixir.SystemLimitError') -> {erl(Meta, '=='), Meta, [Var, system_limit]}; erl_rescue_guard_for(Meta, Var, 'Elixir.ArithmeticError') -> {erl(Meta, '=='), Meta, [Var, badarith]}; erl_rescue_guard_for(Meta, Var, 'Elixir.CondClauseError') -> {erl(Meta, '=='), Meta, [Var, cond_clause]}; erl_rescue_guard_for(Meta, Var, 'Elixir.BadArityError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badarity)); erl_rescue_guard_for(Meta, Var, 'Elixir.BadFunctionError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badfun)); erl_rescue_guard_for(Meta, Var, 'Elixir.MatchError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badmatch)); erl_rescue_guard_for(Meta, Var, 'Elixir.CaseClauseError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, case_clause)); erl_rescue_guard_for(Meta, Var, 'Elixir.TryClauseError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, try_clause)); erl_rescue_guard_for(Meta, Var, 'Elixir.BadStructError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 3), erl_record_compare(Meta, Var, badstruct)); erl_rescue_guard_for(Meta, Var, 'Elixir.BadMapError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badmap)); erl_rescue_guard_for(Meta, Var, 'Elixir.KeyError') -> erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badkey)); erl_rescue_guard_for(Meta, Var, 'Elixir.ArgumentError') -> erl_or(Meta, {erl(Meta, '=='), Meta, [Var, badarg]}, erl_and(Meta, erl_tuple_size(Meta, Var, 2), erl_record_compare(Meta, Var, badarg))); erl_rescue_guard_for(Meta, Var, 'Elixir.ErlangError') -> IsNotTuple = {erl(Meta, 'not'), Meta, [{erl(Meta, is_tuple), Meta, [Var]}]}, IsException = {erl(Meta, '/='), Meta, [ {erl(Meta, element), Meta, [2, Var]}, '__exception__' ]}, erl_or(Meta, IsNotTuple, IsException); erl_rescue_guard_for(_, _, _) -> false. %% Helpers erl_tuple_size(Meta, Var, Size) -> {erl(Meta, '=='), Meta, [{erl(Meta, tuple_size), Meta, [Var]}, Size]}. erl_record_compare(Meta, Var, Expr) -> {erl(Meta, '=='), Meta, [ {erl(Meta, element), Meta, [1, Var]}, Expr ]}. prepend_to_block(_Meta, Expr, {'__block__', Meta, Args}) -> {'__block__', Meta, [Expr|Args]}; prepend_to_block(Meta, Expr, Args) -> {'__block__', Meta, [Expr, Args]}. erl(Meta, Op) -> {'.', Meta, [erlang, Op]}. erl_or(Meta, Left, Right) -> {'__op__', Meta, ['orelse', Left, Right]}. erl_and(Meta, Left, Right) -> {'__op__', Meta, ['andalso', Left, Right]}. elixir-lang-1.1.0~0.20150708/lib/elixir/src/elixir_utils.erl000066400000000000000000000152151254730255300231720ustar00rootroot00000000000000%% Convenience functions used throughout elixir source code %% for ast manipulation and querying. -module(elixir_utils). -export([elixir_to_erl/1, get_line/1, split_last/1, meta_location/1, characters_to_list/1, characters_to_binary/1, macro_name/1, convert_to_boolean/4, returns_boolean/1, atom_concat/1, read_file_type/1, read_link_type/1, relative_to_cwd/1, erl_call/4]). -include("elixir.hrl"). -include_lib("kernel/include/file.hrl"). macro_name(Macro) -> list_to_atom(lists:concat(['MACRO-', Macro])). atom_concat(Atoms) -> list_to_atom(lists:concat(Atoms)). erl_call(Line, Module, Function, Args) -> {call, Line, {remote, Line, {atom, Line, Module}, {atom, Line, Function}}, Args }. get_line(Opts) when is_list(Opts) -> case lists:keyfind(line, 1, Opts) of {line, Line} when is_integer(Line) -> Line; false -> 0 end. split_last([]) -> {[], []}; split_last(List) -> split_last(List, []). split_last([H], Acc) -> {lists:reverse(Acc), H}; split_last([H|T], Acc) -> split_last(T, [H|Acc]). read_file_type(File) -> case file:read_file_info(File) of {ok, #file_info{type=Type}} -> {ok, Type}; {error, _} = Error -> Error end. read_link_type(File) -> case file:read_link_info(File) of {ok, #file_info{type=Type}} -> {ok, Type}; {error, _} = Error -> Error end. relative_to_cwd(Path) -> case elixir_compiler:get_opt(internal) of true -> Path; false -> 'Elixir.Path':relative_to_cwd(Path) end. characters_to_list(Data) when is_list(Data) -> Data; characters_to_list(Data) -> case elixir_compiler:get_opt(internal) of true -> unicode:characters_to_list(Data); false -> 'Elixir.String':to_char_list(Data) end. characters_to_binary(Data) when is_binary(Data) -> Data; characters_to_binary(Data) -> case elixir_compiler:get_opt(internal) of true -> unicode:characters_to_binary(Data); false -> 'Elixir.List':to_string(Data) end. %% Meta location. %% %% Macros add a file+keep pair on location keep %% which we should take into account for report %% reporting. %% %% Returns {binary, integer} on location keep or %% nil. meta_location(Meta) -> case lists:keyfind(file, 1, Meta) of {file, MetaFile} when is_binary(MetaFile) -> case lists:keyfind(keep, 1, Meta) of {keep, MetaLine} when is_integer(MetaLine) -> ok; _ -> MetaLine = 0 end, {MetaFile, MetaLine}; _ -> nil end. %% elixir to erl. Handles only valid quoted expressions, %% that's why things like maps and references are not in the list. elixir_to_erl(Tree) when is_tuple(Tree) -> {tuple, 0, [elixir_to_erl(X) || X <- tuple_to_list(Tree)]}; elixir_to_erl([]) -> {nil, 0}; elixir_to_erl(<<>>) -> {bin, 0, []}; elixir_to_erl(Tree) when is_list(Tree) -> elixir_to_erl_cons_1(Tree, []); elixir_to_erl(Tree) when is_atom(Tree) -> {atom, 0, Tree}; elixir_to_erl(Tree) when is_integer(Tree) -> {integer, 0, Tree}; elixir_to_erl(Tree) when is_float(Tree) -> {float, 0, Tree}; elixir_to_erl(Tree) when is_binary(Tree) -> %% Note that our binaries are utf-8 encoded and we are converting %% to a list using binary_to_list. The reason for this is that Erlang %% considers a string in a binary to be encoded in latin1, so the bytes %% are not changed in any fashion. {bin, 0, [{bin_element, 0, {string, 0, binary_to_list(Tree)}, default, default}]}; elixir_to_erl(Function) when is_function(Function) -> case (erlang:fun_info(Function, type) == {type, external}) andalso (erlang:fun_info(Function, env) == {env, []}) of true -> {module, Module} = erlang:fun_info(Function, module), {name, Name} = erlang:fun_info(Function, name), {arity, Arity} = erlang:fun_info(Function, arity), {'fun', 0, {function, {atom, 0, Module}, {atom, 0, Name}, {integer, 0, Arity}}}; false -> error(badarg) end; elixir_to_erl(Pid) when is_pid(Pid) -> elixir_utils:erl_call(0, erlang, binary_to_term, [elixir_utils:elixir_to_erl(term_to_binary(Pid))]); elixir_to_erl(_Other) -> error(badarg). elixir_to_erl_cons_1([H|T], Acc) -> elixir_to_erl_cons_1(T, [H|Acc]); elixir_to_erl_cons_1(Other, Acc) -> elixir_to_erl_cons_2(Acc, elixir_to_erl(Other)). elixir_to_erl_cons_2([H|T], Acc) -> elixir_to_erl_cons_2(T, {cons, 0, elixir_to_erl(H), Acc}); elixir_to_erl_cons_2([], Acc) -> Acc. %% Boolean checks returns_boolean(Bool) when is_boolean(Bool) -> true; returns_boolean({{'.', _, [erlang, Op]}, _, [_]}) when Op == 'not' -> true; returns_boolean({{'.', _, [erlang, Op]}, _, [_, _]}) when Op == 'and'; Op == 'or'; Op == 'xor'; Op == '=='; Op == '/='; Op == '=<'; Op == '>='; Op == '<'; Op == '>'; Op == '=:='; Op == '=/=' -> true; returns_boolean({'__op__', _, [Op, _, Right]}) when Op == 'andalso'; Op == 'orelse' -> returns_boolean(Right); returns_boolean({{'.', _, [erlang, Fun]}, _, [_]}) when Fun == is_atom; Fun == is_binary; Fun == is_bitstring; Fun == is_boolean; Fun == is_float; Fun == is_function; Fun == is_integer; Fun == is_list; Fun == is_number; Fun == is_pid; Fun == is_port; Fun == is_reference; Fun == is_tuple -> true; returns_boolean({{'.', _, [erlang, Fun]}, _, [_, _]}) when Fun == is_function -> true; returns_boolean({{'.', _, [erlang, Fun]}, _, [_, _, _]}) when Fun == function_exported -> true; returns_boolean({'case', _, [_, [{do, Clauses}]]}) -> lists:all(fun ({'->', _, [_, Expr]}) -> returns_boolean(Expr) end, Clauses); returns_boolean({'cond', _, [[{do, Clauses}]]}) -> lists:all(fun ({'->', _, [_, Expr]}) -> returns_boolean(Expr) end, Clauses); returns_boolean({'__block__', [], Exprs}) -> returns_boolean(lists:last(Exprs)); returns_boolean(_) -> false. convert_to_boolean(Line, Expr, Bool, S) when is_integer(Line) -> case {returns_boolean(Expr), Bool} of {true, true} -> {Expr, S}; {true, false} -> {{op, Line, 'not', Expr}, S}; _ -> do_convert_to_boolean(Line, Expr, Bool, S) end. %% Notice we use a temporary var and bundle nil %% and false checks in the same clause since %% it makes dialyzer happy. do_convert_to_boolean(Line, Expr, Bool, S) -> {Name, _, TS} = elixir_scope:build_var('_', S), Var = {var, Line, Name}, Any = {var, Line, '_'}, OrElse = do_guarded_convert_to_boolean(Line, Var, 'orelse', '=='), FalseResult = {atom, Line, not Bool}, TrueResult = {atom, Line, Bool}, {{'case', Line, Expr, [ {clause, Line, [Var], [[OrElse]], [FalseResult]}, {clause, Line, [Any], [], [TrueResult]} ]}, TS}. do_guarded_convert_to_boolean(Line, Expr, Op, Comp) -> Left = {op, Line, Comp, Expr, {atom, Line, false}}, Right = {op, Line, Comp, Expr, {atom, Line, nil}}, {op, Line, Op, Left, Right}. elixir-lang-1.1.0~0.20150708/lib/elixir/test/000077500000000000000000000000001254730255300201365ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/doc_test.exs000066400000000000000000000013271254730255300224660ustar00rootroot00000000000000ExUnit.start [] defmodule KernelTest do use ExUnit.Case, async: true doctest Access doctest Atom doctest Base doctest Bitwise, import: true doctest Code doctest Collectable doctest Enum doctest Exception doctest Float doctest Inspect doctest Inspect.Algebra doctest Integer doctest IO doctest IO.ANSI doctest Kernel doctest Kernel.SpecialForms doctest Keyword doctest List doctest Macro doctest Map doctest Module doctest Node doctest OptionParser doctest Path doctest Process doctest Protocol doctest Range doctest Record doctest Regex doctest Stream doctest String doctest String.Chars doctest StringIO doctest Tuple doctest URI doctest Version end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/000077500000000000000000000000001254730255300214325ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/access_test.exs000066400000000000000000000033561254730255300244620ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule AccessTest do use ExUnit.Case, async: true # Test nil at compilation time does not fail # and that @config[:foo] has proper precedence. @config nil nil = @config[:foo] @config [foo: :bar] :bar = @config[:foo] @mod :lists [1, 2, 3] = @mod.flatten([1, [2], 3]) @mod -13 -13 = @mod test "for nil" do assert nil[:foo] == nil assert Access.get(nil, :foo) == nil assert_raise ArgumentError, "could not put/update key :foo on a nil value", fn -> Access.get_and_update(nil, :foo, fn nil -> {:ok, :bar} end) end end test "for keywords" do assert [foo: :bar][:foo] == :bar assert [foo: [bar: :baz]][:foo][:bar] == :baz assert [foo: [bar: :baz]][:fuu][:bar] == nil assert Access.get([foo: :bar], :foo) == :bar assert Access.get_and_update([], :foo, fn nil -> {:ok, :baz} end) == {:ok, [foo: :baz]} assert Access.get_and_update([foo: :bar], :foo, fn :bar -> {:ok, :baz} end) == {:ok, [foo: :baz]} end test "for maps" do assert %{foo: :bar}[:foo] == :bar assert %{1 => 1}[1] == 1 assert %{1.0 => 1.0}[1.0] == 1.0 assert %{1 => 1}[1.0] == nil assert Access.get(%{foo: :bar}, :foo) == :bar assert Access.get_and_update(%{}, :foo, fn nil -> {:ok, :baz} end) == {:ok, %{foo: :baz}} assert Access.get_and_update(%{foo: :bar}, :foo, fn :bar -> {:ok, :baz} end) == {:ok, %{foo: :baz}} end test "for atoms" do assert_raise Protocol.UndefinedError, ~r"protocol Access not implemented for :foo", fn -> Access.get(:foo, :bar) end assert_raise Protocol.UndefinedError, ~r"protocol Access not implemented for :foo", fn -> Access.get_and_update(:foo, :bar, fn _ -> {:ok, :baz} end) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/agent_test.exs000066400000000000000000000037521254730255300243170ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule AgentTest do use ExUnit.Case, async: true def identity(state) do state end test "start_link/2 workflow with unregistered name and anonymous functions" do {:ok, pid} = Agent.start_link(fn -> %{} end) {:links, links} = Process.info(self, :links) assert pid in links assert Agent.update(pid, &Map.put(&1, :hello, :world)) == :ok assert Agent.get(pid, &Map.get(&1, :hello), 3000) == :world assert Agent.get_and_update(pid, &Map.pop(&1, :hello), 3000) == :world assert Agent.get(pid, &(&1)) == %{} assert Agent.stop(pid) == :ok wait_until_dead(pid) end test "start/2 workflow with registered name and module functions" do {:ok, pid} = Agent.start(Map, :new, [], name: :agent) assert Process.info(pid, :registered_name) == {:registered_name, :agent} assert Agent.cast(:agent, Map, :put, [:hello, :world]) == :ok assert Agent.get(:agent, Map, :get, [:hello]) == :world assert Agent.get_and_update(:agent, Map, :pop, [:hello]) == :world assert Agent.get(:agent, AgentTest, :identity, []) == %{} assert Agent.stop(:agent) == :ok assert Process.info(pid, :registered_name) == nil end test ":sys.change_code/4 with mfa" do { :ok, pid } = Agent.start_link(fn -> %{} end) :ok = :sys.suspend(pid) mfa = {Map, :put, [:hello, :world]} assert :sys.change_code(pid, __MODULE__, "vsn", mfa) == :ok :ok = :sys.resume(pid) assert Agent.get(pid, &Map.get(&1, :hello)) == :world assert Agent.stop(pid) == :ok end test ":sys.change_code/4 with raising mfa" do { :ok, pid } = Agent.start_link(fn -> %{} end) :ok = :sys.suspend(pid) mfa = { :erlang, :error, [] } assert match?({ :error, _ }, :sys.change_code(pid, __MODULE__, "vsn", mfa)) :ok = :sys.resume(pid) assert Agent.get(pid, &(&1)) == %{} assert Agent.stop(pid) == :ok end defp wait_until_dead(pid) do if Process.alive?(pid) do wait_until_dead(pid) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/application_test.exs000066400000000000000000000024731254730255300255230ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ApplicationTest do use ExUnit.Case, async: true test "application environment" do assert Application.get_env(:elixir, :unknown) == nil assert Application.get_env(:elixir, :unknown, :default) == :default assert Application.fetch_env(:elixir, :unknown) == :error assert_raise ArgumentError, fn -> Application.fetch_env!(:elixir, :unknown) end assert Application.put_env(:elixir, :unknown, :known) == :ok assert Application.fetch_env(:elixir, :unknown) == {:ok, :known} assert Application.fetch_env!(:elixir, :unknown) == :known assert Application.get_env(:elixir, :unknown, :default) == :known assert {:unknown, :known} in Application.get_all_env(:elixir) assert Application.delete_env(:elixir, :unknown) == :ok assert Application.get_env(:elixir, :unknown, :default) == :default end test "application directory" do root = Path.expand("../../../..", __DIR__) assert String.downcase(Application.app_dir(:elixir)) == String.downcase(Path.join(root, "bin/../lib/elixir")) assert String.downcase(Application.app_dir(:elixir, "priv")) == String.downcase(Path.join(root, "bin/../lib/elixir/priv")) assert_raise ArgumentError, fn -> Application.app_dir(:unknown) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/atom_test.exs000066400000000000000000000004151254730255300241520ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule AtomTest do use ExUnit.Case, async: true test "to_string/1" do assert Atom.to_string(:"héllo") == "héllo" end test "to_char_list/1" do assert Atom.to_char_list(:"héllo") == 'héllo' end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/base_test.exs000066400000000000000000000301761254730255300241330ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule BaseTest do use ExUnit.Case, async: true import Base test "encode16" do assert "" == encode16("") assert "66" == encode16("f") assert "666F" == encode16("fo") assert "666F6F" == encode16("foo") assert "666F6F62" == encode16("foob") assert "666F6F6261" == encode16("fooba") assert "666F6F626172" == encode16("foobar") assert "A1B2C3D4E5F67891" == encode16(<<161, 178, 195, 212, 229, 246, 120, 145>>) assert "a1b2c3d4e5f67891" == encode16(<<161, 178, 195, 212, 229, 246, 120, 145>>, case: :lower) end test "decode16" do assert {:ok, ""} == decode16("") assert {:ok, "f"} == decode16("66") assert {:ok, "fo"} == decode16("666F") assert {:ok, "foo"} == decode16("666F6F") assert {:ok, "foob"} == decode16("666F6F62") assert {:ok, "fooba"} == decode16("666F6F6261") assert {:ok, "foobar"} == decode16("666F6F626172") assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} == decode16("A1B2C3D4E5F67891") assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} == decode16("a1b2c3d4e5f67891", case: :lower) assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} == decode16("a1B2c3D4e5F67891", case: :mixed) end test "decode16!" do assert "" == decode16!("") assert "f" == decode16!("66") assert "fo" == decode16!("666F") assert "foo" == decode16!("666F6F") assert "foob" == decode16!("666F6F62") assert "fooba" == decode16!("666F6F6261") assert "foobar" == decode16!("666F6F626172") assert <<161, 178, 195, 212, 229, 246, 120, 145>> == decode16!("A1B2C3D4E5F67891") assert <<161, 178, 195, 212, 229, 246, 120, 145>> == decode16!("a1b2c3d4e5f67891", case: :lower) assert <<161, 178, 195, 212, 229, 246, 120, 145>> == decode16!("a1B2c3D4e5F67891", case: :mixed) end test "decode16 non-alphabet digit" do assert :error == decode16("66KF") assert :error == decode16("66ff") assert :error == decode16("66FF", case: :lower) end test "decode16! non-alphabet digit" do assert_raise ArgumentError, "non-alphabet digit found: K", fn -> decode16!("66KF") end assert_raise ArgumentError, "non-alphabet digit found: f", fn -> decode16!("66ff") end assert_raise ArgumentError, "non-alphabet digit found: F", fn -> decode16!("66FF", case: :lower) end end test "decode16 odd-length string" do assert :error == decode16("666") end test "decode16! odd-length string" do assert_raise ArgumentError, "odd-length string", fn -> decode16!("666") end end test "encode64 empty" do assert "" == encode64("") end test "encode64 two pads" do assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ==" == encode64("Aladdin:open sesame") end test "encode64 one pad" do assert "SGVsbG8gV29ybGQ=" == encode64("Hello World") end test "encode64 no pad" do assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == encode64("Aladdin:open sesam") assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" == encode64(<<"0123456789!@#0^&*();:<>,. []{}">>) end test "decode64 empty" do assert {:ok, ""} == decode64("") end test "decode64! empty" do assert "" == decode64!("") end test "decode64 two pads" do assert {:ok, "Aladdin:open sesame"} == decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ==") end test "decode64! two pads" do assert "Aladdin:open sesame" == decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ==") end test "decode64 one pad" do assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ=") end test "decode64! one pad" do assert "Hello World" == decode64!("SGVsbG8gV29ybGQ=") end test "decode64 no pad" do assert {:ok, "Aladdin:open sesam"} == decode64("QWxhZGRpbjpvcGVuIHNlc2Ft") end test "decode64! no pad" do assert "Aladdin:open sesam" == decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft") end test "decode64 non-alphabet digit" do assert :error == decode64("Zm9)") end test "decode64! non-alphabet digit" do assert_raise ArgumentError, "non-alphabet digit found: )", fn -> decode64!("Zm9)") end end test "decode64 incorrect padding" do assert :error == decode64("SGVsbG8gV29ybGQ") end test "decode64! incorrect padding" do assert_raise ArgumentError, "incorrect padding", fn -> decode64!("SGVsbG8gV29ybGQ") end end test "url_encode64 empty" do assert "" == url_encode64("") end test "url_encode64 two pads" do assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ==" == url_encode64("Aladdin:open sesame") end test "url_encode64 one pad" do assert "SGVsbG8gV29ybGQ=" == url_encode64("Hello World") end test "url_encode64 no pad" do assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == url_encode64("Aladdin:open sesam") assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" == url_encode64(<<"0123456789!@#0^&*();:<>,. []{}">>) end test "url_encode64 no URL unsafe characters" do refute "/3/+/A==" == url_encode64(<<255, 127, 254, 252>>) assert "_3_-_A==" == url_encode64(<<255, 127, 254, 252>>) end test "url_decode64 empty" do assert {:ok, ""} == url_decode64("") end test "url_decode64! empty" do assert "" == url_decode64!("") end test "url_decode64 two pads" do assert {:ok, "Aladdin:open sesame"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ==") end test "url_decode64! two pads" do assert "Aladdin:open sesame" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ==") end test "url_decode64 one pad" do assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ=") end test "url_decode64! one pad" do assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ=") end test "url_decode64 no pad" do assert {:ok, "Aladdin:open sesam"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2Ft") end test "url_decode64! no pad" do assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft") end test "url_decode64 non-alphabet digit" do assert :error == url_decode64("Zm9)") end test "url_decode64! non-alphabet digit" do assert_raise ArgumentError, "non-alphabet digit found: )", fn -> url_decode64!("Zm9)") end end test "url_decode64 incorrect padding" do assert :error == url_decode64("SGVsbG8gV29ybGQ") end test "url_decode64! incorrect padding" do assert_raise ArgumentError, "incorrect padding", fn -> url_decode64!("SGVsbG8gV29ybGQ") end end test "encode32 empty" do assert "" == encode32("") end test "encode32 one pad" do assert "MZXW6YQ=" == encode32("foob") end test "encode32 three pads" do assert "MZXW6===" == encode32("foo") end test "encode32 four pads" do assert "MZXQ====" == encode32("fo") end test "encode32 six pads" do assert "MZXW6YTBOI======" == encode32("foobar") assert "MY======" == encode32("f") end test "encode32 no pads" do assert "MZXW6YTB" == encode32("fooba") end test "encode32 lowercase" do assert "mzxw6ytb" == encode32("fooba", case: :lower) end test "decode32 empty" do assert {:ok, ""} == decode32("") end test "decode32! empty" do assert "" == decode32!("") end test "decode32 one pad" do assert {:ok, "foob"} == decode32("MZXW6YQ=") end test "decode32! one pad" do assert "foob" == decode32!("MZXW6YQ=") end test "decode32 three pads" do assert {:ok, "foo"} == decode32("MZXW6===") end test "decode32! three pads" do assert "foo" == decode32!("MZXW6===") end test "decode32 four pads" do assert {:ok, "fo"} == decode32("MZXQ====") end test "decode32! four pads" do assert "fo" == decode32!("MZXQ====") end test "decode32 lowercase" do assert {:ok, "fo"} == decode32("mzxq====", case: :lower) end test "decode32! lowercase" do assert "fo" == decode32!("mzxq====", case: :lower) end test "decode32 mixed case" do assert {:ok, "fo"} == decode32("mZXq====", case: :mixed) end test "decode32! mixed case" do assert "fo" == decode32!("mZXq====", case: :mixed) end test "decode32 six pads" do assert {:ok, "foobar"} == decode32("MZXW6YTBOI======") assert {:ok, "f"} == decode32("MY======") end test "decode32! six pads" do assert "foobar" == decode32!("MZXW6YTBOI======") assert "f" == decode32!("MY======") end test "decode32 no pads" do assert {:ok, "fooba"} == decode32("MZXW6YTB") end test "decode32! no pads" do assert "fooba" == decode32!("MZXW6YTB") end test "decode32 non-alphabet digit" do assert :error == decode32("MZX)6YTB") assert :error == decode32("66ff") assert :error == decode32("66FF", case: :lower) end test "decode32! non-alphabet digit" do assert_raise ArgumentError, "non-alphabet digit found: )", fn -> decode32!("MZX)6YTB") end assert_raise ArgumentError, "non-alphabet digit found: m", fn -> decode32!("mzxw6ytboi======") end assert_raise ArgumentError, "non-alphabet digit found: M", fn -> decode32!("MZXW6YTBOI======", case: :lower) end end test "decode32 incorrect padding" do assert :error == decode32("MZXW6YQ") end test "decode32! incorrect padding" do assert_raise ArgumentError, "incorrect padding", fn -> decode32!("MZXW6YQ") end end test "hex_encode32 empty" do assert "" == hex_encode32("") end test "hex_encode32 one pad" do assert "CPNMUOG=" == hex_encode32("foob") end test "hex_encode32 three pads" do assert "CPNMU===" == hex_encode32("foo") end test "hex_encode32 four pads" do assert "CPNG====" == hex_encode32("fo") end test "hex_encode32 six pads" do assert "CPNMUOJ1E8======" == hex_encode32("foobar") assert "CO======" == hex_encode32("f") end test "hex_encode32 no pads" do assert "CPNMUOJ1" == hex_encode32("fooba") end test "hex_encode32 lowercase" do assert "cpnmuoj1" == hex_encode32("fooba", case: :lower) end test "hex_decode32 empty" do assert {:ok, ""} == hex_decode32("") end test "hex_decode32! empty" do assert "" == hex_decode32!("") end test "hex_decode32 one pad" do assert {:ok, "foob"} == hex_decode32("CPNMUOG=") end test "hex_decode32! one pad" do assert "foob" == hex_decode32!("CPNMUOG=") end test "hex_decode32 three pads" do assert {:ok, "foo"} == hex_decode32("CPNMU===") end test "hex_decode32! three pads" do assert "foo" == hex_decode32!("CPNMU===") end test "hex_decode32 four pads" do assert {:ok, "fo"} == hex_decode32("CPNG====") end test "hex_decode32! four pads" do assert "fo" == hex_decode32!("CPNG====") end test "hex_decode32 six pads" do assert {:ok, "foobar"} == hex_decode32("CPNMUOJ1E8======") assert {:ok, "f"} == hex_decode32("CO======") end test "hex_decode32! six pads" do assert "foobar" == hex_decode32!("CPNMUOJ1E8======") assert "f" == hex_decode32!("CO======") end test "hex_decode32 no pads" do assert {:ok, "fooba"} == hex_decode32("CPNMUOJ1") end test "hex_decode32! no pads" do assert "fooba" == hex_decode32!("CPNMUOJ1") end test "hex_decode32 non-alphabet digit" do assert :error == hex_decode32("CPN)UOJ1") assert :error == hex_decode32("66f") assert :error == hex_decode32("66F", case: :lower) end test "hex_decode32! non-alphabet digit" do assert_raise ArgumentError, "non-alphabet digit found: )", fn -> hex_decode32!("CPN)UOJ1") end assert_raise ArgumentError, "non-alphabet digit found: c", fn -> hex_decode32!("cpnmuoj1e8======") end assert_raise ArgumentError, "non-alphabet digit found: C", fn -> hex_decode32!("CPNMUOJ1E8======", case: :lower) end end test "hex_decode32 incorrect padding" do assert :error == hex_decode32("CPNMUOG") end test "hex_decode32! incorrect padding" do assert_raise ArgumentError, "incorrect padding", fn -> hex_decode32!("CPNMUOG") end end test "hex_decode32 lowercase" do assert {:ok, "fo"} == hex_decode32("cpng====", case: :lower) end test "hex_decode32! lowercase" do assert "fo" == hex_decode32!("cpng====", case: :lower) end test "hex_decode32 mixed case" do assert {:ok, "fo"} == hex_decode32("cPNg====", case: :mixed) end test "hex_decode32! mixed case" do assert "fo" == hex_decode32!("cPNg====", case: :mixed) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/behaviour_test.exs000066400000000000000000000022271254730255300252010ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule BehaviourTest do use ExUnit.Case, async: true defmodule Sample do use Behaviour defcallback first(integer) :: integer defcallback foo(atom(), binary) :: binary defcallback bar(External.hello, my_var :: binary) :: binary defcallback guarded(my_var) :: my_var when my_var: binary defcallback orr(atom | integer) :: atom defcallback literal(123, {atom}, :atom, [integer], true) :: atom defmacrocallback last(integer) :: Macro.t end test :callbacks do assert Sample.__behaviour__(:callbacks) == [first: 1, guarded: 1, "MACRO-last": 2, literal: 5, orr: 1, foo: 2, bar: 2] end test :specs do assert length(Keyword.get_values(Sample.module_info[:attributes], :callback)) == 7 end test :default_is_not_supported do assert_raise ArgumentError, fn -> defmodule WithDefault do use Behaviour defcallback hello(num \\ 0 :: integer) :: integer end end assert_raise ArgumentError, fn -> defmodule WithDefault do use Behaviour defcallback hello(num :: integer \\ 0) :: integer end end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/bitwise_test.exs000066400000000000000000000015041254730255300246600ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule Bitwise.FunctionsTest do use ExUnit.Case, async: true use Bitwise, skip_operators: true test :bnot do assert bnot(1) == -2 end test :band do assert band(1, 1) == 1 end test :bor do assert bor(0, 1) == 1 end test :bxor do assert bxor(1, 1) == 0 end test :bsl do assert bsl(1, 1) == 2 end test :bsr do assert bsr(1, 1) == 0 end end defmodule Bitwise.OperatorsTest do use ExUnit.Case, async: true use Bitwise, only_operators: true test :bnot do assert ~~~1 == -2 end test :band do assert (1 &&& 1) == 1 end test :bor do assert (0 ||| 1) == 1 end test :bxor do assert 1 ^^^ 1 == 0 end test :bsl do assert (1 <<< 1) == 2 end test :bsr do assert (1 >>> 1) == 0 end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/code_test.exs000066400000000000000000000117521254730255300241320ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule CodeTest do use ExUnit.Case, async: true import PathHelpers def genmodule(name) do defmodule name do Kernel.LexicalTracker.remotes(__MODULE__) end end contents = quote do defmodule CodeTest.Sample do def eval_quoted_info, do: {__MODULE__, __ENV__.file, __ENV__.line} end end Code.eval_quoted contents, [], file: "sample.ex", line: 13 test :eval_string do assert Code.eval_string("1 + 2") == {3, []} assert {3, _} = Code.eval_string("a + b", [a: 1, b: 2], Macro.Env.location(__ENV__)) end test :eval_string_with_other_context do assert Code.eval_string("var!(a, Sample) = 1") == {1, [{{:a, Sample}, 1}]} end test :eval_binary_errors do msg = "nofile:2: a binary field without size is only allowed at the end of a binary pattern" assert_raise CompileError, msg, fn -> Code.eval_string(""" foo = "foo" "\\"" <> bar <> "\\"" = foo """) end end test :eval_with_unnamed_scopes do assert {%RuntimeError{}, [a: %RuntimeError{}]} = Code.eval_string("a = (try do (raise \"hello\") rescue e -> e end)") end test :eval_options do assert Code.eval_string("is_atom(:foo) and K.is_list([])", [], functions: [{Kernel, [is_atom: 1]}], macros: [{Kernel, [..: 2, and: 2]}], aliases: [{K, Kernel}], requires: [Kernel]) == {true, []} end test :eval_stacktrace do try do Code.eval_string("<>", a: :a, b: :b) rescue _ -> assert System.stacktrace |> Enum.any?(&(elem(&1, 0) == __MODULE__)) end end test :eval_with_requires do assert Code.eval_string("Kernel.if true, do: :ok", [], requires: [Z, Kernel]) == {:ok, []} end test :eval_quoted do assert Code.eval_quoted(quote(do: 1 + 2)) == {3, []} assert CodeTest.Sample.eval_quoted_info() == {CodeTest.Sample, "sample.ex", 13} end test :eval_quoted_with_env do alias :lists, as: MyList assert Code.eval_quoted(quote(do: MyList.flatten [[1, 2, 3]]), [], __ENV__) == {[1, 2, 3], []} end test :eval_file do assert Code.eval_file(fixture_path("code_sample.exs")) == {3, [var: 3]} assert_raise Code.LoadError, fn -> Code.eval_file("non_existent.exs") end end test :require do Code.require_file fixture_path("code_sample.exs") assert fixture_path("code_sample.exs") in Code.loaded_files assert Code.require_file(fixture_path("code_sample.exs")) == nil Code.unload_files [fixture_path("code_sample.exs")] refute fixture_path("code_sample.exs") in Code.loaded_files assert Code.require_file(fixture_path("code_sample.exs")) != nil end test :string_to_quoted do assert Code.string_to_quoted("1 + 2") == {:ok, {:+, [line: 1], [1, 2]}} assert Code.string_to_quoted!("1 + 2") == {:+, [line: 1], [1, 2]} assert Code.string_to_quoted("a.1") == {:error, {1, "syntax error before: ", "1"}} assert_raise SyntaxError, fn -> Code.string_to_quoted!("a.1") end end test :string_to_quoted_existing_atoms_only do assert :badarg = catch_error(Code.string_to_quoted!(":thereisnosuchatom", existing_atoms_only: true)) end test :string_to_quoted! do assert Code.string_to_quoted!("1 + 2") == {:+, [line: 1], [1, 2]} assert_raise SyntaxError, fn -> Code.string_to_quoted!("a.1") end assert_raise TokenMissingError, fn -> Code.string_to_quoted!("1 +") end end test :compile_source do assert __MODULE__.__info__(:compile)[:source] == String.to_char_list(__ENV__.file) end test :compile_info_returned_with_source_accessible_through_keyword_module do compile = __MODULE__.__info__(:compile) assert Keyword.get(compile, :source) != nil end test :compile_string_works_accross_lexical_scopes do assert [{CompileCrossSample, _}] = Code.compile_string("CodeTest.genmodule CompileCrossSample") after :code.purge CompileCrossSample :code.delete CompileCrossSample end test :compile_string do assert [{CompileStringSample, _}] = Code.compile_string("defmodule CompileStringSample, do: :ok") after :code.purge CompileSimpleSample :code.delete CompileSimpleSample end test :compile_quoted do assert [{CompileQuotedSample, _}] = Code.compile_string("defmodule CompileQuotedSample, do: :ok") after :code.purge CompileQuotedSample :code.delete CompileQuotedSample end test :ensure_loaded? do assert Code.ensure_loaded?(__MODULE__) refute Code.ensure_loaded?(Unknown.Module) end test :ensure_compiled? do assert Code.ensure_compiled?(__MODULE__) refute Code.ensure_compiled?(Unknown.Module) end end defmodule Code.SyncTest do use ExUnit.Case test :path_manipulation do path = Path.join(__DIR__, "fixtures") Code.prepend_path path assert to_char_list(path) in :code.get_path Code.delete_path path refute to_char_list(path) in :code.get_path end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/dict_test.exs000066400000000000000000000345611254730255300241460ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ # A TestDict implementation used only for testing. defmodule TestDict do defstruct list: [] def new(list \\ []) when is_list(list) do %TestDict{list: list} end def size(%TestDict{list: list}) do length(list) end def update(%TestDict{list: list} = map, key, initial, fun) do %{map | list: update(list, key, initial, fun)} end def update([{key, value}|list], key, _initial, fun) do [{key, fun.(value)}|list] end def update([{_, _} = e|list], key, initial, fun) do [e|update(list, key, initial, fun)] end def update([], key, initial, _fun) do [{key, initial}] end defimpl Enumerable do def reduce(%{list: list}, acc, fun), do: Enumerable.List.reduce(list, acc, fun) def member?(%{list: list}, other), do: Enumerable.List.member(list, other) def count(%{list: list}), do: Enumerable.List.count(list) end end defmodule DictTest.Common do defmacro __using__(_) do quote location: :keep do import Enum, only: [sort: 1] defp new_dict(list \\ [{"first_key", 1}, {"second_key", 2}]) do Enum.into list, dict_impl.new end defp new_dict(list, transform) do Enum.into list, dict_impl.new, transform end defp int_dict do Enum.into [{1, 1}], dict_impl.new end test "access" do dict = new_dict() assert dict["first_key"] == 1 assert dict["other_key"] == nil end test "access uses match operation" do dict = int_dict() assert dict[1] == 1 assert dict[1.0] == nil end test "get/2 and get/3" do dict = new_dict() assert Dict.get(dict, "first_key") == 1 assert Dict.get(dict, "second_key") == 2 assert Dict.get(dict, "other_key") == nil assert Dict.get(dict, "other_key", 3) == 3 end test "get/2 with match" do assert Dict.get(int_dict, 1) == 1 assert Dict.get(int_dict, 1.0) == nil end test "get_lazy/3" do dict = new_dict() Process.put(:get_lazy, 42) fun = fn -> Process.put(:get_lazy, Process.get(:get_lazy) + 1) Process.get(:get_lazy) end assert Dict.get_lazy(dict, "first_key", fun) == 1 assert Dict.get_lazy(dict, "second_key", fun) == 2 assert Dict.get_lazy(dict, "other_key", fun) == 43 assert Dict.get_lazy(dict, "first_key", fun) == 1 assert Dict.get_lazy(dict, "other_key", fun) == 44 end test "get_and_update/3 when the key is present" do dict = new_dict() {get, dict} = Dict.get_and_update dict, "first_key", fn(current_val) -> {[current_val: current_val], :new_value} end assert get == [current_val: 1] assert Dict.get(dict, "first_key") == :new_value assert Dict.get(dict, "second_key") == 2 end test "get_and_update/3 when the key is not present" do dict = new_dict() {get, dict} = Dict.get_and_update dict, "new_key", fn(current_val) -> {[current_val: current_val], :new_value} end assert get == [current_val: nil] assert Dict.get(dict, "first_key") == 1 assert Dict.get(dict, "second_key") == 2 assert Dict.get(dict, "new_key") == :new_value end test "fetch/2" do dict = new_dict() assert Dict.fetch(dict, "first_key") == {:ok, 1} assert Dict.fetch(dict, "second_key") == {:ok, 2} assert Dict.fetch(dict, "other_key") == :error end test "fetch/2 with match" do assert Dict.fetch(int_dict, 1) == {:ok, 1} assert Dict.fetch(int_dict, 1.0) == :error end test "fetch!/2" do dict = new_dict() assert Dict.fetch!(dict, "first_key") == 1 assert Dict.fetch!(dict, "second_key") == 2 assert_raise KeyError, fn -> Dict.fetch!(dict, "other_key") end end test "put/3" do dict = new_dict() |> Dict.put("first_key", {1}) assert Dict.get(dict, "first_key") == {1} assert Dict.get(dict, "second_key") == 2 end test "put/3 with_match" do dict = int_dict() assert Dict.get(Dict.put(dict, 1, :other), 1) == :other assert Dict.get(Dict.put(dict, 1.0, :other), 1) == 1 assert Dict.get(Dict.put(dict, 1, :other), 1.0) == nil assert Dict.get(Dict.put(dict, 1.0, :other), 1.0) == :other end test "put_new/3" do dict = Dict.put_new(new_dict(), "first_key", {1}) assert Dict.get(dict, "first_key") == 1 end test "put_new/3 with_match" do assert Dict.get(Dict.put_new(int_dict, 1, :other), 1) == 1 assert Dict.get(Dict.put_new(int_dict, 1.0, :other), 1) == 1 assert Dict.get(Dict.put_new(int_dict, 1, :other), 1.0) == nil assert Dict.get(Dict.put_new(int_dict, 1.0, :other), 1.0) == :other end test "put_new_lazy/3" do Process.put(:put_new_lazy, 42) fun = fn -> Process.put(:put_new_lazy, Process.get(:put_new_lazy) + 1) Process.get(:put_new_lazy) end assert Dict.get(Dict.put_new_lazy(new_dict(), "other_key", fun), "other_key") == 43 assert Dict.get(Dict.put_new_lazy(new_dict(), "first_key", fun), "first_key") == 1 assert Dict.get(Dict.put_new_lazy(new_dict(), "another_key", fun), "another_key") == 44 end test "keys/1" do assert Enum.sort(Dict.keys(new_dict())) == ["first_key", "second_key"] assert Dict.keys(new_dict([])) == [] end test "values/1" do assert Enum.sort(Dict.values(new_dict())) == [1, 2] assert Dict.values(new_dict([])) == [] end test "delete/2" do dict = Dict.delete(new_dict(), "second_key") assert Dict.size(dict) == 1 assert Dict.has_key?(dict, "first_key") refute Dict.has_key?(dict, "second_key") dict = Dict.delete(new_dict(), "other_key") assert dict == new_dict() assert Dict.size(dict) == 2 end test "delete/2 with match" do assert Dict.get(Dict.delete(int_dict, 1), 1) == nil assert Dict.get(Dict.delete(int_dict, 1.0), 1) == 1 end test "merge/2" do dict = new_dict() assert Dict.merge(new_dict([]), dict) == dict assert Dict.merge(dict, new_dict([])) == dict assert Dict.merge(dict, dict) == dict assert Dict.merge(new_dict([]), new_dict([])) == new_dict([]) dict1 = new_dict [{"a", 1}, {"b", 2}, {"c", 3}] dict2 = new_dict [{"a", 3}, {"c", :a}, {"d", 0}] assert Dict.merge(dict1, dict2) |> Enum.sort == [{"a", 3}, {"b", 2}, {"c", :a}, {"d", 0}] end test "merge/2 with other dict" do dict1 = new_dict [{"a", 1}, {"b", 2}, {"c", 3}] dict2 = TestDict.new [{"a", 3}, {"c", :a}, {"d", 0}] actual = Dict.merge(dict1, dict2) assert Dict.merge(dict1, dict2) |> Enum.sort == [{"a", 3}, {"b", 2}, {"c", :a}, {"d", 0}] assert Dict.merge(dict2, dict1) |> Enum.sort == [{"a", 1}, {"b", 2}, {"c", 3}, {"d", 0}] end test "merge/3" do dict1 = new_dict [{"a", 1}, {"b", 2}] dict2 = new_dict [{"a", 3}, {"d", 4}] actual = Dict.merge dict1, dict2, fn _k, v1, v2 -> v1 + v2 end assert Enum.sort(actual) == [{"a", 4}, {"b", 2}, {"d", 4}] end test "has_key?/2" do dict = new_dict() assert Dict.has_key?(dict, "first_key") refute Dict.has_key?(dict, "other_key") end test "has_key?/2 with match" do assert Dict.has_key?(int_dict, 1) refute Dict.has_key?(int_dict, 1.0) end test "size/1" do assert Dict.size(new_dict()) == 2 assert Dict.size(new_dict([])) == 0 end test "update!/3" do dict = Dict.update!(new_dict(), "first_key", fn val -> -val end) assert Dict.get(dict, "first_key") == -1 assert_raise KeyError, fn -> Dict.update!(new_dict(), "non-existent", fn val -> -val end) end end test "update!/3 with match" do assert Dict.get(Dict.update!(int_dict(), 1, &(&1 + 1)), 1) == 2 end test "update/4" do dict = Dict.update(new_dict(), "first_key", 0, fn val -> -val end) assert Dict.get(dict, "first_key") == -1 dict = Dict.update(new_dict(), "non-existent", "...", fn val -> -val end) assert Dict.get(dict, "non-existent") == "..." end test "update/4 with match" do dict = int_dict() assert Dict.get(Dict.update(dict, 1.0, 2, &(&1 + 1)), 1) == 1 assert Dict.get(Dict.update(dict, 1.0, 2, &(&1 + 1)), 1.0) == 2 end test "pop/2 and pop/3" do dict = new_dict() {v, actual} = Dict.pop(dict, "first_key") assert v == 1 assert actual == new_dict([{"second_key", 2}]) {v, actual} = Dict.pop(dict, "other_key") assert v == nil assert dict == actual {v, actual} = Dict.pop(dict, "other_key", "default") assert v == "default" assert dict == actual end test "pop/2 and pop/3 with match" do dict = int_dict() {v, actual} = Dict.pop(dict, 1) assert v == 1 assert Enum.sort(actual) == [] {v, actual} = Dict.pop(dict, 1.0) assert v == nil assert actual == dict end test "pop_lazy/3" do dict = new_dict() Process.put(:pop_lazy, 42) fun = fn -> Process.put(:pop_lazy, Process.get(:pop_lazy) + 1) Process.get(:pop_lazy) end {v, actual} = Dict.pop_lazy(dict, "other_key", fun) assert v == 43 assert dict == actual {v, actual} = Dict.pop_lazy(dict, "first_key", fun) assert v == 1 assert actual == new_dict([{"second_key", 2}]) {v, actual} = Dict.pop_lazy(dict, "other_key", fun) assert v == 44 assert dict == actual end test "split/2" do dict = new_dict() {take, drop} = Dict.split(dict, []) assert take == new_dict([]) assert drop == dict {take, drop} = Dict.split(dict, ["unknown_key"]) assert take == new_dict([]) assert drop == dict split_keys = ["first_key", "second_key", "unknown_key"] {take, drop} = Dict.split(dict, split_keys) take_expected = new_dict([]) |> Dict.put("first_key", 1) |> Dict.put("second_key", 2) drop_expected = new_dict([]) |> Dict.delete("first_key") |> Dict.delete("second_key") assert Enum.sort(take) == Enum.sort(take_expected) assert Enum.sort(drop) == Enum.sort(drop_expected) end test "split/2 with match" do dict = int_dict() {take, drop} = Dict.split(dict, [1]) assert take == dict assert drop == new_dict([]) {take, drop} = Dict.split(dict, [1.0]) assert take == new_dict([]) assert drop == dict end test "split/2 with enum" do dict = int_dict() {take, drop} = Dict.split(dict, 1..3) assert take == dict assert drop == new_dict([]) end test "take/2" do dict = new_dict() take = Dict.take(dict, ["unknown_key"]) assert take == new_dict([]) take = Dict.take(dict, ["first_key"]) assert take == new_dict([{"first_key", 1}]) end test "take/2 with match" do dict = int_dict() assert Dict.take(dict, [1]) == dict assert Dict.take(dict, [1.0]) == new_dict([]) end test "take/2 with enum" do dict = int_dict() assert Dict.take(dict, 1..3) == dict end test "drop/2" do dict = new_dict() drop = Dict.drop(dict, ["unknown_key"]) assert drop == dict drop = Dict.drop(dict, ["first_key"]) assert drop == new_dict([{"second_key", 2}]) end test "drop/2 with match" do dict = int_dict() assert Dict.drop(dict, [1]) == new_dict([]) assert Dict.drop(dict, [1.0]) == dict end test "drop/2 with enum" do dict = int_dict() assert Dict.drop(dict, 1..3) == new_dict([]) end test "equal?/2" do dict1 = new_dict(a: 2, b: 3, f: 5, c: 123) dict2 = new_dict(a: 2, b: 3, f: 5, c: 123) assert dict_impl.equal?(dict1, dict2) assert Dict.equal?(dict1, dict2) dict2 = Dict.put(dict2, :a, 3) refute dict_impl.equal?(dict1, dict2) refute Dict.equal?(dict1, dict2) dict3 = [a: 2, b: 3, f: 5, c: 123, z: 666] refute Dict.equal?(dict1, dict3) refute Dict.equal?(dict3, dict1) end test "equal?/2 with match" do dict1 = new_dict([{1, 1}]) dict2 = new_dict([{1.0, 1}]) assert Dict.equal?(dict1, dict1) refute Dict.equal?(dict1, dict2) end test "equal?/2 with other dict" do dict = new_dict([{1, 1}]) assert Dict.equal?(dict, TestDict.new([{1, 1}])) refute Dict.equal?(dict, TestDict.new([{1.0, 1}])) end test "is enumerable" do dict = new_dict() assert Enum.empty?(new_dict([])) refute Enum.empty?(dict) assert Enum.member?(dict, {"first_key", 1}) refute Enum.member?(dict, {"first_key", 2}) assert Enum.count(dict) == 2 assert Enum.reduce(dict, 0, fn({k, v}, acc) -> v + acc end) == 3 end test "is collectable" do dict = new_dict() assert Dict.size(dict) == 2 assert Enum.sort(dict) == [{"first_key", 1}, {"second_key", 2}] dict = new_dict([{1}, {2}, {3}], fn {x} -> {<>, x} end) assert Dict.size(dict) == 3 assert Enum.sort(dict) == [{"A", 1}, {"B", 2}, {"C", 3}] end test "is zippable" do dict = new_dict() list = Dict.to_list(dict) assert Enum.zip(list, list) == Enum.zip(dict, dict) dict = new_dict(1..120, fn i -> {i, i} end) list = Dict.to_list(dict) assert Enum.zip(list, list) == Enum.zip(dict, dict) end end end end defmodule Dict.HashDictTest do use ExUnit.Case, async: true use DictTest.Common doctest Dict defp dict_impl, do: HashDict end defmodule Dict.MapDictTest do use ExUnit.Case, async: true use DictTest.Common doctest Dict defp dict_impl, do: Map end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/enum_test.exs000066400000000000000000001117311254730255300241620ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule EnumTest.List do use ExUnit.Case, async: true test :empty? do assert Enum.empty?([]) refute Enum.empty?([1, 2, 3]) refute Enum.empty?(1..3) end test :member? do assert Enum.member?([1, 2, 3], 2) refute Enum.member?([], 0) refute Enum.member?([1, 2, 3], 0) assert Enum.member?(1..3, 2) refute Enum.member?(1..3, 0) end test :count do assert Enum.count([1, 2, 3]) == 3 assert Enum.count([]) == 0 end test :count_fun do assert Enum.count([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) == 1 assert Enum.count([], fn(x) -> rem(x, 2) == 0 end) == 0 end test :all? do assert Enum.all?([2, 4, 6], fn(x) -> rem(x, 2) == 0 end) refute Enum.all?([2, 3, 4], fn(x) -> rem(x, 2) == 0 end) assert Enum.all?([2, 4, 6]) refute Enum.all?([2, nil, 4]) assert Enum.all?([]) end test :any? do refute Enum.any?([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) assert Enum.any?([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) refute Enum.any?([false, false, false]) assert Enum.any?([false, true, false]) assert Enum.any?([:foo, false, false]) refute Enum.any?([false, nil, false]) refute Enum.any?([]) end test :at do assert Enum.at([2, 4, 6], 0) == 2 assert Enum.at([2, 4, 6], 2) == 6 assert Enum.at([2, 4, 6], 4) == nil assert Enum.at([2, 4, 6], 4, :none) == :none assert Enum.at([2, 4, 6], -2) == 4 assert Enum.at([2, 4, 6], -4) == nil end test :concat_1 do assert Enum.concat([[1, [2], 3], [4], [5, 6]]) == [1, [2], 3, 4, 5, 6] assert Enum.concat(1..3, []) == [1, 2, 3] assert Enum.concat([[], []]) == [] assert Enum.concat([[]]) == [] assert Enum.concat([]) == [] assert Enum.concat([1..5, fn acc, _ -> acc end, [1]]) == [1, 2, 3, 4, 5, 1] end test :concat_2 do assert Enum.concat([], [1]) == [1] assert Enum.concat([1, [2], 3], [4, 5]) == [1, [2], 3, 4, 5] assert Enum.concat(1..3, []) == [1, 2, 3] assert Enum.concat([], []) == [] assert Enum.concat(fn acc, _ -> acc end, [1]) == [1] end test :fetch! do assert Enum.fetch!([2, 4, 6], 0) == 2 assert Enum.fetch!([2, 4, 6], 2) == 6 assert Enum.fetch!([2, 4, 6], -2) == 4 assert_raise Enum.OutOfBoundsError, fn -> Enum.fetch!([2, 4, 6], 4) end assert_raise Enum.OutOfBoundsError, fn -> Enum.fetch!([2, 4, 6], -4) end end test :dedup do assert Enum.dedup([1, 1, 2, 1, 1, 2, 1]) == [1, 2, 1, 2, 1] assert Enum.dedup([2, 1, 1, 2, 1]) == [2, 1, 2, 1] assert Enum.dedup([1, 2, 3, 4]) == [1, 2, 3, 4] assert Enum.dedup([1, 1.0, 2.0, 2]) == [1, 1.0, 2.0, 2] assert Enum.dedup([]) == [] assert Enum.dedup([nil, nil, true, {:value, true}]) == [nil, true, {:value, true}] assert Enum.dedup([nil]) == [nil] end test :dedup_by do assert Enum.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) == [{1, :x}, {2, :y}, {1, :x}] assert Enum.dedup_by([5, 1, 2, 3, 2, 1], fn x -> x > 2 end) == [5, 1, 3, 2] end test :drop do assert Enum.drop([1, 2, 3], 0) == [1, 2, 3] assert Enum.drop([1, 2, 3], 1) == [2, 3] assert Enum.drop([1, 2, 3], 2) == [3] assert Enum.drop([1, 2, 3], 3) == [] assert Enum.drop([1, 2, 3], 4) == [] assert Enum.drop([1, 2, 3], -1) == [1, 2] assert Enum.drop([1, 2, 3], -2) == [1] assert Enum.drop([1, 2, 3], -4) == [] assert Enum.drop([], 3) == [] end test :drop_while do assert Enum.drop_while([1, 2, 3, 4, 3, 2, 1], fn(x) -> x <= 3 end) == [4, 3, 2, 1] assert Enum.drop_while([1, 2, 3], fn(_) -> false end) == [1, 2, 3] assert Enum.drop_while([1, 2, 3], fn(x) -> x <= 3 end) == [] assert Enum.drop_while([], fn(_) -> false end) == [] end test :find do assert Enum.find([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) == nil assert Enum.find([2, 4, 6], 0, fn(x) -> rem(x, 2) == 1 end) == 0 assert Enum.find([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) == 3 end test :find_value do assert Enum.find_value([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) == nil assert Enum.find_value([2, 4, 6], 0, fn(x) -> rem(x, 2) == 1 end) == 0 assert Enum.find_value([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) end test :find_index do assert Enum.find_index([2, 4, 6], fn(x) -> rem(x, 2) == 1 end) == nil assert Enum.find_index([2, 3, 4], fn(x) -> rem(x, 2) == 1 end) == 1 end test :each do assert Enum.each([], fn(x) -> x end) == :ok assert Enum.each([1, 2, 3], fn(x) -> Process.put(:enum_test_each, x * 2) end) == :ok assert Process.get(:enum_test_each) == 6 after Process.delete(:enum_test_each) end test :fetch do assert Enum.fetch([2, 4, 6], 0) == {:ok, 2} assert Enum.fetch([2, 4, 6], 2) == {:ok, 6} assert Enum.fetch([2, 4, 6], 4) == :error assert Enum.fetch([2, 4, 6], -2) == {:ok, 4} assert Enum.fetch([2, 4, 6], -4) == :error end test :filter do assert Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) == [2] assert Enum.filter([2, 4, 6], fn(x) -> rem(x, 2) == 0 end) == [2, 4, 6] end test :filter_with_match do assert Enum.filter([1, 2, 3], &match?(1, &1)) == [1] assert Enum.filter([1, 2, 3], &match?(x when x < 3, &1)) == [1, 2] assert Enum.filter([1, 2, 3], &match?(_, &1)) == [1, 2, 3] end test :filter_map do assert Enum.filter_map([1, 2, 3], fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) == [4] assert Enum.filter_map([2, 4, 6], fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) == [4, 8, 12] end test :flat_map do assert Enum.flat_map([], fn(x) -> [x, x] end) == [] assert Enum.flat_map([1, 2, 3], fn(x) -> [x, x] end) == [1, 1, 2, 2, 3, 3] assert Enum.flat_map([1, 2, 3], fn(x) -> x..x+1 end) == [1, 2, 2, 3, 3, 4] end test :flat_map_reduce do assert Enum.flat_map_reduce([1, 2, 3], 0, &{[&1, &2], &1 + &2}) == {[1, 0, 2, 1, 3, 3], 6} assert Enum.flat_map_reduce(1..100, 0, fn i, acc -> if acc < 3, do: {[i], acc + 1}, else: {:halt, acc} end) == {[1, 2, 3], 3} end test :group_by do assert Enum.group_by([], fn -> nil end) == %{} assert Enum.group_by(1..6, &rem(&1, 3)) == %{0 => [6, 3], 1 => [4, 1], 2 => [5, 2]} result = Enum.group_by(1..6, %{3 => :default}, &rem(&1, 3)) assert result[0] == [6, 3] assert result[3] == :default end test :into do assert Enum.into([a: 1, b: 2], %{}) == %{a: 1, b: 2} assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3} assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2] assert Enum.into([1, 2, 3], "numbers: ", &to_string/1) == "numbers: 123" end test :intersperse do assert Enum.intersperse([], true) == [] assert Enum.intersperse([1], true) == [1] assert Enum.intersperse([1, 2, 3], true) == [1, true, 2, true, 3] end test :join do assert Enum.join([], " = ") == "" assert Enum.join([1, 2, 3], " = ") == "1 = 2 = 3" assert Enum.join([1, "2", 3], " = ") == "1 = 2 = 3" assert Enum.join([1, 2, 3]) == "123" assert Enum.join(["", "", 1, 2, "", 3, "", "\n"], ";") == ";;1;2;;3;;\n" assert Enum.join([""]) == "" end test :map_join do assert Enum.map_join([], " = ", &(&1 * 2)) == "" assert Enum.map_join([1, 2, 3], " = ", &(&1 * 2)) == "2 = 4 = 6" assert Enum.map_join([1, 2, 3], &(&1 * 2)) == "246" assert Enum.map_join(["", "", 1, 2, "", 3, "", "\n"], ";", &(&1)) == ";;1;2;;3;;\n" assert Enum.map_join([""], "", &(&1)) == "" end test :join_empty do fun = fn (acc, _) -> acc end assert Enum.join(fun, ".") == "" assert Enum.map_join(fun, ".", &(&1 + 0)) == "" end test :map do assert Enum.map([], fn x -> x * 2 end) == [] assert Enum.map([1, 2, 3], fn x -> x * 2 end) == [2, 4, 6] end test :map_reduce do assert Enum.map_reduce([], 1, fn(x, acc) -> {x * 2, x + acc} end) == {[], 1} assert Enum.map_reduce([1, 2, 3], 1, fn(x, acc) -> {x * 2, x + acc} end) == {[2, 4, 6], 7} end test :partition do assert Enum.partition([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) == {[2], [1, 3]} assert Enum.partition([2, 4, 6], fn(x) -> rem(x, 2) == 0 end) == {[2, 4, 6], []} end test :reduce do assert Enum.reduce([], 1, fn(x, acc) -> x + acc end) == 1 assert Enum.reduce([1, 2, 3], 1, fn(x, acc) -> x + acc end) == 7 assert Enum.reduce([1, 2, 3], fn(x, acc) -> x + acc end) == 6 assert_raise Enum.EmptyError, fn -> Enum.reduce([], fn(x, acc) -> x + acc end) end end test :reduce_while do assert Enum.reduce_while(1..100, 0, fn i, acc -> if i <= 3, do: {:cont, acc + i}, else: {:halt, acc} end) == 6 assert Enum.reduce_while([1, 2, 3], 1, fn i, acc -> {:cont, acc + i} end) == 7 assert Enum.reduce_while([1, 2, 3], 1, fn _i, acc -> {:halt, acc} end) == 1 assert Enum.reduce_while([], 0, fn _i, acc -> {:cont, acc} end) == 0 end test :reject do assert Enum.reject([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) == [1, 3] assert Enum.reject([2, 4, 6], fn(x) -> rem(x, 2) == 0 end) == [] end test :reverse do assert Enum.reverse([]) == [] assert Enum.reverse([1, 2, 3]) == [3, 2, 1] assert Enum.reverse([1, 2, 3], [4, 5, 6]) == [3, 2, 1, 4, 5, 6] end test :reverse_slice do assert Enum.reverse_slice([], 1, 2) == [] assert Enum.reverse_slice([1, 2, 3], 0, 0) == [1, 2, 3] assert Enum.reverse_slice([1, 2, 3], 0, 1) == [1, 2, 3] assert Enum.reverse_slice([1, 2, 3], 0, 2) == [2, 1, 3] assert Enum.reverse_slice([1, 2, 3], 0, 20000000) == [3, 2, 1] assert Enum.reverse_slice([1, 2, 3], 100, 2) == [1, 2, 3] assert Enum.reverse_slice([1, 2, 3], 10, 10) == [1, 2, 3] end test :random_1 do # corner cases, independent of the seed assert_raise Enum.EmptyError, fn -> Enum.random([]) end assert Enum.random([1]) == 1 # set a fixed seed so the test can be deterministic # please note the order of following assertions is important seed1 = {1406, 407414, 139258} seed2 = {1406, 421106, 567597} :random.seed(seed1) assert Enum.random([1, 2]) == 2 assert Enum.random([1, 2, 3]) == 2 assert Enum.random([1, 2, 3, 4]) == 4 assert Enum.random([1, 2, 3, 4, 5]) == 1 :random.seed(seed2) assert Enum.random([1, 2]) == 1 assert Enum.random([1, 2, 3]) == 3 assert Enum.random([1, 2, 3, 4]) == 1 assert Enum.random([1, 2, 3, 4, 5]) == 5 end test :random_2 do # corner cases, independent of the seed assert_raise FunctionClauseError, fn -> Enum.random([1, 2], -1) end assert Enum.random([], 0) == [] assert Enum.random([], 3) == [] assert Enum.random([1], 0) == [] assert Enum.random([1], 2) == [1] assert Enum.random([1, 2], 0) == [] # set a fixed seed so the test can be deterministic # please note the order of following assertions is important seed1 = {1406, 407414, 139258} seed2 = {1406, 421106, 567597} :random.seed(seed1) assert Enum.random([1, 2, 3, 4, 5], 1) == [2] assert Enum.random([1, 2, 3, 4, 5], 2) == [4, 1] assert Enum.random([1, 2, 3, 4, 5], 3) == [1, 3, 5] assert Enum.random([1, 2, 3, 4, 5], 4) == [3, 5, 1, 2] assert Enum.random([1, 2, 3, 4, 5], 5) == [1, 2, 5, 4, 3] assert Enum.random([1, 2, 3, 4, 5], 6) == [2, 4, 5, 3, 1] :random.seed(seed2) assert Enum.random([1, 2, 3, 4, 5], 1) == [1] assert Enum.random([1, 2, 3, 4, 5], 2) == [1, 5] assert Enum.random([1, 2, 3, 4, 5], 3) == [5, 1, 3] assert Enum.random([1, 2, 3, 4, 5], 4) == [4, 5, 2, 1] assert Enum.random([1, 2, 3, 4, 5], 5) == [4, 3, 1, 5, 2] assert Enum.random([1, 2, 3, 4, 5], 6) == [5, 2, 1, 4, 3] # assert that every item in the sample comes from the input list list = for _<-1..100, do: make_ref for x <- Enum.random(list, 50) do assert Enum.find(list, &(&1 == x)) end end test :scan do assert Enum.scan([1, 2, 3, 4, 5], &(&1 + &2)) == [1, 3, 6, 10, 15] assert Enum.scan([], &(&1 + &2)) == [] assert Enum.scan([1, 2, 3, 4, 5], 0, &(&1 + &2)) == [1, 3, 6, 10, 15] assert Enum.scan([], 0, &(&1 + &2)) == [] end test :shuffle do # set a fixed seed so the test can be deterministic :random.seed(1374, 347975, 449264) assert Enum.shuffle([1, 2, 3, 4, 5]) == [2, 4, 1, 5, 3] end test :sort do assert Enum.sort([5, 3, 2, 4, 1]) == [1, 2, 3, 4, 5] assert Enum.sort([5, 3, 2, 4, 1], &(&1 > &2)) == [5, 4, 3, 2, 1] end test :sort_by do collection = [ [other_data: 1, sorted_data: 5], [other_data: 3, sorted_data: 4], [other_data: 4, sorted_data: 3], [other_data: 2, sorted_data: 2], [other_data: 5, sorted_data: 1] ] assert Enum.sort_by( collection, &(&1[:sorted_data]) ) == [ [other_data: 5, sorted_data: 1], [other_data: 2, sorted_data: 2], [other_data: 4, sorted_data: 3], [other_data: 3, sorted_data: 4], [other_data: 1, sorted_data: 5] ] assert Enum.sort_by(collection, &(&1[:sorted_data]), &>=/2) == collection end test :split do assert Enum.split([1, 2, 3], 0) == {[], [1, 2, 3]} assert Enum.split([1, 2, 3], 1) == {[1], [2, 3]} assert Enum.split([1, 2, 3], 2) == {[1, 2], [3]} assert Enum.split([1, 2, 3], 3) == {[1, 2, 3], []} assert Enum.split([1, 2, 3], 4) == {[1, 2, 3], []} assert Enum.split([], 3) == {[], []} assert Enum.split([1, 2, 3], -1) == {[1, 2], [3]} assert Enum.split([1, 2, 3], -2) == {[1], [2, 3]} assert Enum.split([1, 2, 3], -3) == {[], [1, 2, 3]} assert Enum.split([1, 2, 3], -10) == {[], [1, 2, 3]} end test :split_while do assert Enum.split_while([1, 2, 3], fn(_) -> false end) == {[], [1, 2, 3]} assert Enum.split_while([1, 2, 3], fn(_) -> true end) == {[1, 2, 3], []} assert Enum.split_while([1, 2, 3], fn(x) -> x > 2 end) == {[], [1, 2, 3]} assert Enum.split_while([1, 2, 3], fn(x) -> x > 3 end) == {[], [1, 2, 3]} assert Enum.split_while([1, 2, 3], fn(x) -> x < 3 end) == {[1, 2], [3]} assert Enum.split_while([], fn(_) -> true end) == {[], []} end test :sum do assert Enum.sum([]) == 0 assert Enum.sum([1]) == 1 assert Enum.sum([1, 2, 3]) == 6 assert Enum.sum([1.1, 2.2, 3.3]) == 6.6 assert_raise ArithmeticError, fn -> Enum.sum([{}]) end assert_raise ArithmeticError, fn -> Enum.sum([1, {}]) end end test :take do assert Enum.take([1, 2, 3], 0) == [] assert Enum.take([1, 2, 3], 1) == [1] assert Enum.take([1, 2, 3], 2) == [1, 2] assert Enum.take([1, 2, 3], 3) == [1, 2, 3] assert Enum.take([1, 2, 3], 4) == [1, 2, 3] assert Enum.take([1, 2, 3], -1) == [3] assert Enum.take([1, 2, 3], -2) == [2, 3] assert Enum.take([1, 2, 3], -4) == [1, 2, 3] assert Enum.take([], 3) == [] end test :take_every do assert Enum.take_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2) == [1, 3, 5, 7, 9] assert Enum.take_every([], 2) == [] assert Enum.take_every([1, 2], 2) == [1] assert Enum.take_every([1, 2, 3], 0) == [] assert_raise FunctionClauseError, fn -> Enum.take_every([1, 2, 3], -1) end end test :take_while do assert Enum.take_while([1, 2, 3], fn(x) -> x > 3 end) == [] assert Enum.take_while([1, 2, 3], fn(x) -> x <= 1 end) == [1] assert Enum.take_while([1, 2, 3], fn(x) -> x <= 3 end) == [1, 2, 3] assert Enum.take_while([], fn(_) -> true end) == [] end test :to_list do assert Enum.to_list([]) == [] assert Enum.to_list(1 .. 3) == [1, 2, 3] end test :uniq_by do assert Enum.uniq_by([1, 2, 3, 2, 1], fn x -> x end) == [1, 2, 3] end test :uniq do assert Enum.uniq([5, 1, 2, 3, 2, 1]) == [5, 1, 2, 3] assert Enum.uniq([1, 2, 3, 2, 1], fn x -> x end) == [1, 2, 3] end test :zip do assert Enum.zip([:a, :b], [1, 2]) == [{:a, 1}, {:b, 2}] assert Enum.zip([:a, :b], [1, 2, 3, 4]) == [{:a, 1}, {:b, 2}] assert Enum.zip([:a, :b, :c, :d], [1, 2]) == [{:a, 1}, {:b, 2}] assert Enum.zip([], [1]) == [] assert Enum.zip([1], []) == [] assert Enum.zip([], []) == [] end test :unzip do assert Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}]) == {[:a, :b, :c], [1, 2, 3]} assert Enum.unzip([]) == {[], []} assert Enum.unzip(%{a: 1, b: 2}) == {[:a, :b], [1, 2]} assert Enum.unzip([foo: "a", bar: "b"]) == {[:foo, :bar], ["a", "b"]} assert_raise FunctionClauseError, fn -> Enum.unzip([{:a, 1}, {:b, 2, "foo"}]) end assert_raise FunctionClauseError, fn -> Enum.unzip([{1, 2, {3, {4, 5}}}]) end assert_raise FunctionClauseError, fn -> Enum.unzip([1, 2, 3]) end end test :with_index do assert Enum.with_index([]) == [] assert Enum.with_index([1, 2, 3]) == [{1, 0}, {2, 1}, {3, 2}] end test :max do assert Enum.max([1]) == 1 assert Enum.max([1, 2, 3]) == 3 assert Enum.max([1, [], :a, {}]) == [] assert_raise Enum.EmptyError, fn -> Enum.max([]) end end test :max_by do assert Enum.max_by(["a", "aa", "aaa"], fn(x) -> String.length(x) end) == "aaa" assert_raise Enum.EmptyError, fn -> Enum.max_by([], fn(x) -> String.length(x) end) end end test :min do assert Enum.min([1]) == 1 assert Enum.min([1, 2, 3]) == 1 assert Enum.min([[], :a, {}]) == :a assert_raise Enum.EmptyError, fn -> Enum.min([]) end end test :min_by do assert Enum.min_by(["a", "aa", "aaa"], fn(x) -> String.length(x) end) == "a" assert_raise Enum.EmptyError, fn -> Enum.min_by([], fn(x) -> String.length(x) end) end end test :minmax do assert Enum.minmax([1]) == {1, 1} assert Enum.minmax([2, 3, 1]) == {1, 3} assert Enum.minmax([[], :a, {}]) == {:a, []} assert_raise Enum.EmptyError, fn -> Enum.minmax([]) end end test :minmax_by do assert Enum.minmax_by(["aaa", "a", "aa"], fn(x) -> String.length(x) end) == {"a", "aaa"} assert_raise Enum.EmptyError, fn -> Enum.minmax_by([], fn(x) -> String.length(x) end) end end test :chunk do assert Enum.chunk([1, 2, 3, 4, 5], 2) == [[1, 2], [3, 4]] assert Enum.chunk([1, 2, 3, 4, 5], 2, 2, [6]) == [[1, 2], [3, 4], [5, 6]] assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2) == [[1, 2, 3], [3, 4, 5]] assert Enum.chunk([1, 2, 3, 4, 5, 6], 2, 3) == [[1, 2], [4, 5]] assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]] assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 3, []) == [[1, 2, 3], [4, 5, 6]] assert Enum.chunk([1, 2, 3, 4, 5], 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]] end test :chunk_by do assert Enum.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1)) == [[1], [2, 2], [3], [4, 4, 6], [7, 7]] assert Enum.chunk_by([1, 2, 3, 4], fn _ -> true end) == [[1, 2, 3, 4]] assert Enum.chunk_by([], fn _ -> true end) == [] assert Enum.chunk_by([1], fn _ -> true end) == [[1]] end test :slice do assert Enum.slice([1, 2, 3, 4, 5], 0, 0) == [] assert Enum.slice([1, 2, 3, 4, 5], 0, 1) == [1] assert Enum.slice([1, 2, 3, 4, 5], 0, 2) == [1, 2] assert Enum.slice([1, 2, 3, 4, 5], 1, 2) == [2, 3] assert Enum.slice([1, 2, 3, 4, 5], 1, 0) == [] assert Enum.slice([1, 2, 3, 4, 5], 2, 5) == [3, 4, 5] assert Enum.slice([1, 2, 3, 4, 5], 2, 6) == [3, 4, 5] assert Enum.slice([1, 2, 3, 4, 5], 5, 5) == [] assert Enum.slice([1, 2, 3, 4, 5], 6, 5) == [] assert Enum.slice([1, 2, 3, 4, 5], 6, 0) == [] assert Enum.slice([1, 2, 3, 4, 5], -6, 0) == [] assert Enum.slice([1, 2, 3, 4, 5], -6, 5) == [] assert Enum.slice([1, 2, 3, 4, 5], -2, 5) == [4, 5] assert Enum.slice([1, 2, 3, 4, 5], -3, 1) == [3] end test :slice_range do assert Enum.slice([1, 2, 3, 4, 5], 0..0) == [1] assert Enum.slice([1, 2, 3, 4, 5], 0..1) == [1, 2] assert Enum.slice([1, 2, 3, 4, 5], 0..2) == [1, 2, 3] assert Enum.slice([1, 2, 3, 4, 5], 1..2) == [2, 3] assert Enum.slice([1, 2, 3, 4, 5], 1..0) == [] assert Enum.slice([1, 2, 3, 4, 5], 2..5) == [3, 4, 5] assert Enum.slice([1, 2, 3, 4, 5], 2..6) == [3, 4, 5] assert Enum.slice([1, 2, 3, 4, 5], 4..4) == [5] assert Enum.slice([1, 2, 3, 4, 5], 5..5) == [] assert Enum.slice([1, 2, 3, 4, 5], 6..5) == [] assert Enum.slice([1, 2, 3, 4, 5], 6..0) == [] assert Enum.slice([1, 2, 3, 4, 5], -6..0) == [] assert Enum.slice([1, 2, 3, 4, 5], -6..5) == [] assert Enum.slice([1, 2, 3, 4, 5], -5..-1) == [1, 2, 3, 4, 5] assert Enum.slice([1, 2, 3, 4, 5], -5..-3) == [1, 2, 3] assert Enum.slice([1, 2, 3, 4, 5], -6..-1) == [] assert Enum.slice([1, 2, 3, 4, 5], -6..-3) == [] end end defmodule EnumTest.Range do use ExUnit.Case, async: true test :all? do range = 0..5 refute Enum.all?(range, fn(x) -> rem(x, 2) == 0 end) range = 0..1 assert Enum.all?(range, fn(x) -> x < 2 end) assert Enum.all?(range) range = 1..0 assert Enum.all?(range) end test :any? do range = 0..5 refute Enum.any?(range, &(&1 > 10)) range = 0..5 assert Enum.any?(range, &(&1 > 3)) range = 1..0 assert Enum.any?(range) end test :fetch! do assert Enum.fetch!(2..6, 0) == 2 assert Enum.fetch!(2..6, 4) == 6 assert Enum.fetch!(2..6, -1) == 6 assert Enum.fetch!(2..6, -2) == 5 assert Enum.fetch!(-2..-6, 0) == -2 assert Enum.fetch!(-2..-6, 4) == -6 assert_raise Enum.OutOfBoundsError, fn -> Enum.fetch!(2..6, 8) end assert_raise Enum.OutOfBoundsError, fn -> Enum.fetch!(-2..-6, 8) end assert_raise Enum.OutOfBoundsError, fn -> Enum.fetch!(2..6, -8) end end test :count do range = 1..5 assert Enum.count(range) == 5 range = 1..1 assert Enum.count(range) == 1 assert Enum.count([1, true, false, nil]) == 4 end test :count_fun do range = 1..5 assert Enum.count(range, fn(x) -> rem(x, 2) == 0 end) == 2 range = 1..1 assert Enum.count(range, fn(x) -> rem(x, 2) == 0 end) == 0 assert Enum.count([1, true, false, nil], & &1) == 2 end test :chunk do assert Enum.chunk(1..5, 2) == [[1, 2], [3, 4]] assert Enum.chunk(1..5, 2, 2, [6]) == [[1, 2], [3, 4], [5, 6]] assert Enum.chunk(1..6, 3, 2) == [[1, 2, 3], [3, 4, 5]] assert Enum.chunk(1..6, 2, 3) == [[1, 2], [4, 5]] assert Enum.chunk(1..6, 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]] assert Enum.chunk(1..5, 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]] end test :chunk_by do assert Enum.chunk_by(1..4, fn _ -> true end) == [[1, 2, 3, 4]] assert Enum.chunk_by(1..4, &(rem(&1, 2) == 1)) == [[1], [2], [3], [4]] end test :dedup do assert Enum.dedup(1..3) == [1, 2, 3] end test :dedup_by do assert Enum.dedup_by(1..3, fn _ -> 1 end) == [1] end test :drop do range = 1..3 assert Enum.drop(range, 0) == [1, 2, 3] assert Enum.drop(range, 1) == [2, 3] assert Enum.drop(range, 2) == [3] assert Enum.drop(range, 3) == [] assert Enum.drop(range, 4) == [] assert Enum.drop(range, -1) == [1, 2] assert Enum.drop(range, -2) == [1] assert Enum.drop(range, -4) == [] range = 1..0 assert Enum.drop(range, 3) == [] end test :drop_while do range = 0..6 assert Enum.drop_while(range, fn(x) -> x <= 3 end) == [4, 5, 6] assert Enum.drop_while(range, fn(_) -> false end) == [0, 1, 2, 3, 4, 5, 6] range = 0..3 assert Enum.drop_while(range, fn(x) -> x <= 3 end) == [] range = 1..0 assert Enum.drop_while(range, fn(_) -> nil end) == [1, 0] end test :find do range = 2..6 assert Enum.find(range, fn(x) -> rem(x, 2) == 0 end) == 2 assert Enum.find(range, fn(x) -> rem(x, 2) == 1 end) == 3 assert Enum.find(range, fn _ -> false end) == nil assert Enum.find(range, 0, fn _ -> false end) == 0 end test :find_value do range = 2..6 assert Enum.find_value(range, fn(x) -> rem(x, 2) == 1 end) end test :find_index do range = 2..6 assert Enum.find_index(range, fn(x) -> rem(x, 2) == 1 end) == 1 end test :empty? do range = 1..0 refute Enum.empty?(range) range = 1..2 refute Enum.empty?(range) end test :each do try do range = 1..0 assert Enum.each(range, fn(x) -> x end) == :ok range = 1..3 assert Enum.each(range, fn(x) -> Process.put(:enum_test_each, x * 2) end) == :ok assert Process.get(:enum_test_each) == 6 after Process.delete(:enum_test_each) end try do range = -1..-3 assert Enum.each(range, fn(x) -> Process.put(:enum_test_each, x * 2) end) == :ok assert Process.get(:enum_test_each) == -6 after Process.delete(:enum_test_each) end end test :filter do range = 1..3 assert Enum.filter(range, fn(x) -> rem(x, 2) == 0 end) == [2] range = 1..6 assert Enum.filter(range, fn(x) -> rem(x, 2) == 0 end) == [2, 4, 6] assert Enum.filter([1, 2, false, 3, nil], & &1) == [1, 2, 3] end test :filter_with_match do range = 1..3 assert Enum.filter(range, &match?(1, &1)) == [1] assert Enum.filter(range, &match?(x when x < 3, &1)) == [1, 2] assert Enum.filter(range, &match?(_, &1)) == [1, 2, 3] end test :filter_map do range = 1..3 assert Enum.filter_map(range, fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) == [4] range = 2..6 assert Enum.filter_map(range, fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) == [4, 8, 12] end test :flat_map do range = 1..3 assert Enum.flat_map(range, fn(x) -> [x, x] end) == [1, 1, 2, 2, 3, 3] end test :intersperse do range = 1..0 assert Enum.intersperse(range, true) == [1, true, 0] range = 1..3 assert Enum.intersperse(range, false) == [1, false, 2, false, 3] end test :into do assert Enum.into([a: 1, b: 2], %{}) == %{a: 1, b: 2} assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2] assert Enum.into(3..5, [1, 2]) == [1, 2, 3, 4, 5] assert Enum.into(1..5, []) == [1, 2, 3, 4, 5] assert Enum.into(1..5, [], fn x -> x * 2 end) == [2, 4, 6, 8, 10] assert Enum.into(1..3, "numbers: ", &to_string/1) == "numbers: 123" end test :join do range = 1..0 assert Enum.join(range, " = ") == "1 = 0" range = 1..3 assert Enum.join(range, " = ") == "1 = 2 = 3" assert Enum.join(range) == "123" end test :map_join do range = 1..0 assert Enum.map_join(range, " = ", &(&1 * 2)) == "2 = 0" range = 1..3 assert Enum.map_join(range, " = ", &(&1 * 2)) == "2 = 4 = 6" assert Enum.map_join(range, &(&1 * 2)) == "246" end test :map do range = 1..3 assert Enum.map(range, fn x -> x * 2 end) == [2, 4, 6] range = -1..-3 assert Enum.map(range, fn x -> x * 2 end) == [-2, -4, -6] end test :map_reduce do range = 1..0 assert Enum.map_reduce(range, 1, fn(x, acc) -> {x * 2, x + acc} end) == {[2, 0], 2} range = 1..3 assert Enum.map_reduce(range, 1, fn(x, acc) -> {x * 2, x + acc} end) == {[2, 4, 6], 7} end test :max do assert Enum.max(1..1) == 1 assert Enum.max(1..3) == 3 assert Enum.max(3..1) == 3 end test :max_by do assert Enum.max_by(1..1, fn(x) -> :math.pow(-2, x) end) == 1 assert Enum.max_by(1..3, fn(x) -> :math.pow(-2, x) end) == 2 end test :min do assert Enum.min(1..1) == 1 assert Enum.min(1..3) == 1 end test :min_by do assert Enum.min_by(1..1, fn(x) -> :math.pow(-2, x) end) == 1 assert Enum.min_by(1..3, fn(x) -> :math.pow(-2, x) end) == 3 end test :partition do range = 1..3 assert Enum.partition(range, fn(x) -> rem(x, 2) == 0 end) == {[2], [1, 3]} end test :reduce do range = 1..0 assert Enum.reduce(range, 1, fn(x, acc) -> x + acc end) == 2 range = 1..3 assert Enum.reduce(range, 1, fn(x, acc) -> x + acc end) == 7 range = 1..3 assert Enum.reduce(range, fn(x, acc) -> x + acc end) == 6 end test :reject do range = 1..3 assert Enum.reject(range, fn(x) -> rem(x, 2) == 0 end) == [1, 3] range = 1..6 assert Enum.reject(range, fn(x) -> rem(x, 2) == 0 end) == [1, 3, 5] assert Enum.reject([1, true, nil, false, 2], & &1) == [nil, false] end test :reverse do assert Enum.reverse(0..0) == [0] assert Enum.reverse(1..3) == [3, 2, 1] assert Enum.reverse(1..3, 4..6) == [3, 2, 1, 4, 5, 6] assert Enum.reverse([1, 2, 3], 4..6) == [3, 2, 1, 4, 5, 6] assert Enum.reverse(1..3, [4, 5, 6]) == [3, 2, 1, 4, 5, 6] end test :reverse_slice do assert Enum.reverse_slice(1..6, 2, 0) == [1, 2, 3, 4, 5, 6] assert Enum.reverse_slice(1..6, 2, 2) == [1, 2, 4, 3, 5, 6] assert Enum.reverse_slice(1..6, 2, 4) == [1, 2, 6, 5, 4, 3] assert Enum.reverse_slice(1..6, 2, 10000000) == [1, 2, 6, 5, 4, 3] assert Enum.reverse_slice(1..6, 10000000, 4) == [1, 2, 3, 4, 5, 6] assert Enum.reverse_slice(1..6, 50, 50) == [1, 2, 3, 4, 5, 6] end test :random_1 do # corner cases, independent of the seed assert Enum.random(1..1) == 1 # set a fixed seed so the test can be deterministic # please note the order of following assertions is important seed1 = {1406, 407414, 139258} seed2 = {1406, 421106, 567597} :random.seed(seed1) assert Enum.random(1..2) == 2 assert Enum.random(1..3) == 2 assert Enum.random(1..4) == 4 assert Enum.random(1..5) == 1 :random.seed(seed1) assert Enum.random(?a..?z) == ?i :random.seed(seed1) assert Enum.random(?0..?9) == ?8 :random.seed(seed2) assert Enum.random(1..2) == 1 assert Enum.random(1..3) == 3 assert Enum.random(1..4) == 1 assert Enum.random(1..5) == 5 :random.seed(seed2) assert Enum.random(?a..?z) == ?a :random.seed(seed2) assert Enum.random(?0..?9) == ?0 end test :random_2 do # corner cases, independent of the seed assert_raise FunctionClauseError, fn -> Enum.random(1..2, -1) end assert Enum.random(1..1, 0) == [] assert Enum.random(1..1, 2) == [1] assert Enum.random(1..2, 0) == [] # set a fixed seed so the test can be deterministic # please note the order of following assertions is important seed1 = {1406, 407414, 139258} seed2 = {1406, 421106, 567597} :random.seed(seed1) assert Enum.random(1..5, 1) == [2] assert Enum.random(1..5, 2) == [4, 1] assert Enum.random(1..5, 3) == [1, 3, 5] assert Enum.random(1..5, 4) == [3, 5, 1, 2] assert Enum.random(1..5, 5) == [1, 2, 5, 4, 3] assert Enum.random(1..5, 6) == [2, 4, 5, 3, 1] :random.seed(seed2) assert Enum.random(1..5, 1) == [1] assert Enum.random(1..5, 2) == [1, 5] assert Enum.random(1..5, 3) == [5, 1, 3] assert Enum.random(1..5, 4) == [4, 5, 2, 1] assert Enum.random(1..5, 5) == [4, 3, 1, 5, 2] assert Enum.random(1..5, 6) == [5, 2, 1, 4, 3] :random.seed(seed1) assert Enum.random(?a..?z, 1) == 'i' assert Enum.random(?a..?z, 2) == 'cm' assert Enum.random(?a..?z, 3) == 'alp' assert Enum.random(?a..?z, 4) == 'tzmd' assert Enum.random(?a..?z, 5) == 'cuxvb' :random.seed(seed2) assert Enum.random(?a..?z, 1) == 'a' assert Enum.random(?a..?z, 2) == 'wk' assert Enum.random(?a..?z, 3) == 'ayj' assert Enum.random(?a..?z, 4) == 'rbcm' assert Enum.random(?a..?z, 5) == 'rhzju' :random.seed(seed1) assert Enum.random(?0..?9, 1) == '8' assert Enum.random(?0..?9, 2) == '07' assert Enum.random(?0..?9, 3) == '018' assert Enum.random(?0..?9, 4) == '0856' assert Enum.random(?0..?9, 5) == '03698' :random.seed(seed2) assert Enum.random(?0..?9, 1) == '0' assert Enum.random(?0..?9, 2) == '48' assert Enum.random(?0..?9, 3) == '590' assert Enum.random(?0..?9, 4) == '4805' assert Enum.random(?0..?9, 5) == '81945' end test :scan do assert Enum.scan(1..5, &(&1 + &2)) == [1, 3, 6, 10, 15] assert Enum.scan(1..5, 0, &(&1 + &2)) == [1, 3, 6, 10, 15] end test :shuffle do # set a fixed seed so the test can be deterministic :random.seed(1374, 347975, 449264) assert Enum.shuffle(1..5) == [2, 4, 1, 5, 3] end test :slice do assert Enum.slice(1..5, 0, 0) == [] assert Enum.slice(1..5, 0, 1) == [1] assert Enum.slice(1..5, 0, 2) == [1, 2] assert Enum.slice(1..5, 1, 2) == [2, 3] assert Enum.slice(1..5, 1, 0) == [] assert Enum.slice(1..5, 2, 5) == [3, 4, 5] assert Enum.slice(1..5, 2, 6) == [3, 4, 5] assert Enum.slice(1..5, 5, 5) == [] assert Enum.slice(1..5, 6, 5) == [] assert Enum.slice(1..5, 6, 0) == [] assert Enum.slice(1..5, -6, 0) == [] assert Enum.slice(1..5, -6, 5) == [] assert Enum.slice(1..5, -2, 5) == [4, 5] assert Enum.slice(1..5, -3, 1) == [3] end test :slice_range do assert Enum.slice(1..5, 0..0) == [1] assert Enum.slice(1..5, 0..1) == [1, 2] assert Enum.slice(1..5, 0..2) == [1, 2, 3] assert Enum.slice(1..5, 1..2) == [2, 3] assert Enum.slice(1..5, 1..0) == [] assert Enum.slice(1..5, 2..5) == [3, 4, 5] assert Enum.slice(1..5, 2..6) == [3, 4, 5] assert Enum.slice(1..5, 4..4) == [5] assert Enum.slice(1..5, 5..5) == [] assert Enum.slice(1..5, 6..5) == [] assert Enum.slice(1..5, 6..0) == [] assert Enum.slice(1..5, -6..0) == [] assert Enum.slice(1..5, -6..5) == [] assert Enum.slice(1..5, -5..-1) == [1, 2, 3, 4, 5] assert Enum.slice(1..5, -5..-3) == [1, 2, 3] assert Enum.slice(1..5, -6..-1) == [] assert Enum.slice(1..5, -6..-3) == [] end test :sort do assert Enum.sort(3..1) == [1, 2, 3] assert Enum.sort(2..1) == [1, 2] assert Enum.sort(1..1) == [1] assert Enum.sort(3..1, &(&1 > &2)) == [3, 2, 1] assert Enum.sort(2..1, &(&1 > &2)) == [2, 1] assert Enum.sort(1..1, &(&1 > &2)) == [1] end test :split do range = 1..3 assert Enum.split(range, 0) == {[], [1, 2, 3]} assert Enum.split(range, 1) == {[1], [2, 3]} assert Enum.split(range, 2) == {[1, 2], [3]} assert Enum.split(range, 3) == {[1, 2, 3], []} assert Enum.split(range, 4) == {[1, 2, 3], []} assert Enum.split(range, -1) == {[1, 2], [3]} assert Enum.split(range, -2) == {[1], [2, 3]} assert Enum.split(range, -3) == {[], [1, 2, 3]} assert Enum.split(range, -10) == {[], [1, 2, 3]} range = 1..0 assert Enum.split(range, 3) == {[1, 0], []} end test :split_while do range = 1..3 assert Enum.split_while(range, fn(_) -> false end) == {[], [1, 2, 3]} assert Enum.split_while(range, fn(_) -> nil end) == {[], [1, 2, 3]} assert Enum.split_while(range, fn(_) -> true end) == {[1, 2, 3], []} assert Enum.split_while(range, fn(x) -> x > 2 end) == {[], [1, 2, 3]} assert Enum.split_while(range, fn(x) -> x > 3 end) == {[], [1, 2, 3]} assert Enum.split_while(range, fn(x) -> x < 3 end) == {[1, 2], [3]} assert Enum.split_while(range, fn(x) -> x end) == {[1, 2, 3], []} range = 1..0 assert Enum.split_while(range, fn(_) -> true end) == {[1, 0], []} end test :sum do assert Enum.sum(1..1) == 1 assert Enum.sum(1..3) == 6 end test :take do range = 1..3 assert Enum.take(range, 0) == [] assert Enum.take(range, 1) == [1] assert Enum.take(range, 2) == [1, 2] assert Enum.take(range, 3) == [1, 2, 3] assert Enum.take(range, 4) == [1, 2, 3] assert Enum.take(range, -1) == [3] assert Enum.take(range, -2) == [2, 3] assert Enum.take(range, -4) == [1, 2, 3] range = 1..0 assert Enum.take(range, 3) == [1, 0] end test :take_every do assert Enum.take_every(1..10, 2) == [1, 3, 5, 7, 9] assert Enum.take_every(1..2, 2) == [1] assert Enum.take_every(1..3, 0) == [] assert_raise FunctionClauseError, fn -> Enum.take_every(1..3, -1) end end test :take_while do range = 1..3 assert Enum.take_while(range, fn(x) -> x > 3 end) == [] assert Enum.take_while(range, fn(x) -> x <= 1 end) == [1] assert Enum.take_while(range, fn(x) -> x <= 3 end) == [1, 2, 3] assert Enum.take_while(range, fn(x) -> x end) == [1, 2, 3] assert Enum.take_while(range, fn(_) -> nil end) == [] assert Enum.take_while([], fn(_) -> true end) == [] end test :uniq do assert Enum.uniq(1..3) == [1, 2, 3] assert Enum.uniq(1..3, fn x -> x end) == [1, 2, 3] end test :zip do assert Enum.zip([:a, :b], 1..2) == [{:a, 1}, {:b, 2}] assert Enum.zip([:a, :b], 1..4) == [{:a, 1}, {:b, 2}] assert Enum.zip([:a, :b, :c, :d], 1..2) == [{:a, 1}, {:b, 2}] assert Enum.zip(1..2, [:a, :b]) == [{1, :a}, {2, :b}] assert Enum.zip(1..4, [:a, :b]) == [{1, :a}, {2, :b}] assert Enum.zip(1..2, [:a, :b, :c, :d]) == [{1, :a}, {2, :b}] assert Enum.zip(1..2, 1..2) == [{1, 1}, {2, 2}] assert Enum.zip(1..4, 1..2) == [{1, 1}, {2, 2}] assert Enum.zip(1..2, 1..4) == [{1, 1}, {2, 2}] end test :with_index do assert Enum.with_index(1..3) == [{1, 0}, {2, 1}, {3, 2}] end end defmodule EnumTest.SideEffects do use ExUnit.Case, async: true import ExUnit.CaptureIO import PathHelpers test "take with side effects" do stream = Stream.unfold(1, fn x -> IO.puts x; {x, x + 1} end) assert capture_io(fn -> Enum.take(stream, 1) end) == "1\n" end test "take does not consume next without a need" do path = tmp_path("oneliner.txt") File.mkdir(Path.dirname(path)) try do File.write!(path, "ONE") File.open!(path, [], fn file -> iterator = IO.stream(file, :line) assert Enum.take(iterator, 1) == ["ONE"] assert Enum.take(iterator, 5) == [] end) after File.rm(path) end end test "take with no item works as no-op" do iterator = File.stream!(fixture_path("unknown.txt")) assert Enum.take(iterator, 0) == [] assert Enum.take(iterator, 0) == [] assert Enum.take(iterator, 0) == [] assert Enum.take(iterator, 0) == [] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/exception_test.exs000066400000000000000000000352101254730255300252110ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ExceptionTest do use ExUnit.Case, async: true test "raise preserves the stacktrace" do stacktrace = try do raise "a" rescue _ -> [top|_] = System.stacktrace top end file = __ENV__.file |> Path.relative_to_cwd |> String.to_char_list assert {__MODULE__, :"test raise preserves the stacktrace", _, [file: ^file, line: 9]} = stacktrace end test "exception?" do assert Exception.exception?(%RuntimeError{}) refute Exception.exception?(%Regex{}) refute Exception.exception?({}) end test "message" do defmodule BadException do def message(exception) do if exception.raise do raise "oops" end end end assert Exception.message(%{__struct__: BadException, __exception__: true, raise: true}) =~ "got RuntimeError with message `oops` while retrieving Exception.message/1 " <> "for %{__exception__: true, __struct__: ExceptionTest.BadException, raise: true}" assert Exception.message(%{__struct__: BadException, __exception__: true, raise: false}) =~ "got nil while retrieving Exception.message/1 " <> "for %{__exception__: true, __struct__: ExceptionTest.BadException, raise: false}" end test "normalize" do assert Exception.normalize(:throw, :badarg) == :badarg assert Exception.normalize(:exit, :badarg) == :badarg assert Exception.normalize({:EXIT, self}, :badarg) == :badarg assert Exception.normalize(:error, :badarg).__struct__ == ArgumentError assert Exception.normalize(:error, %ArgumentError{}).__struct__ == ArgumentError end test "format without stacktrace" do stacktrace = try do throw(:stack) catch :stack -> System.stacktrace() end assert Exception.format(:error, :badarg) == "** (ArgumentError) argument error\n" <> Exception.format_stacktrace(stacktrace) end test "format with empty stacktrace" do assert Exception.format(:error, :badarg, []) == "** (ArgumentError) argument error" end test "format with EXIT has no stacktrace" do assert Exception.format({:EXIT, self}, :badarg) == "** (EXIT from #{inspect self}) :badarg" end test "format_banner" do assert Exception.format_banner(:error, :badarg) == "** (ArgumentError) argument error" assert Exception.format_banner(:throw, :badarg) == "** (throw) :badarg" assert Exception.format_banner(:exit, :badarg) == "** (exit) :badarg" assert Exception.format_banner({:EXIT, self}, :badarg) == "** (EXIT from #{inspect self}) :badarg" end test "format_stacktrace from file" do assert_raise ArgumentError, fn -> Code.eval_string("def foo do end", [], file: "myfile") end assert Exception.format_stacktrace(System.stacktrace) =~ "myfile:1: (file)" end test "format_stacktrace from module" do assert_raise ArgumentError, fn -> Code.eval_string("defmodule Foo do raise ArgumentError, ~s(oops) end", [], file: "myfile") end assert Exception.format_stacktrace(System.stacktrace) =~ "myfile:1: (module)" end test "format_stacktrace_entry with no file or line" do assert Exception.format_stacktrace_entry({Foo, :bar, [1, 2, 3], []}) == "Foo.bar(1, 2, 3)" assert Exception.format_stacktrace_entry({Foo, :bar, [], []}) == "Foo.bar()" assert Exception.format_stacktrace_entry({Foo, :bar, 1, []}) == "Foo.bar/1" end test "format_stacktrace_entry with file and line" do assert Exception.format_stacktrace_entry({Foo, :bar, [], [file: 'file.ex', line: 10]}) == "file.ex:10: Foo.bar()" assert Exception.format_stacktrace_entry({Foo, :bar, [1, 2, 3], [file: 'file.ex', line: 10]}) == "file.ex:10: Foo.bar(1, 2, 3)" assert Exception.format_stacktrace_entry({Foo, :bar, 1, [file: 'file.ex', line: 10]}) == "file.ex:10: Foo.bar/1" end test "format_stacktrace_entry with file no line" do assert Exception.format_stacktrace_entry({Foo, :bar, [], [file: 'file.ex']}) == "file.ex: Foo.bar()" assert Exception.format_stacktrace_entry({Foo, :bar, [], [file: 'file.ex', line: 0]}) == "file.ex: Foo.bar()" assert Exception.format_stacktrace_entry({Foo, :bar, [1, 2, 3], [file: 'file.ex']}) == "file.ex: Foo.bar(1, 2, 3)" assert Exception.format_stacktrace_entry({Foo, :bar, 1, [file: 'file.ex']}) == "file.ex: Foo.bar/1" end test "format_stacktrace_entry with application" do assert Exception.format_stacktrace_entry({Exception, :bar, [], [file: 'file.ex']}) == "(elixir) file.ex: Exception.bar()" assert Exception.format_stacktrace_entry({Exception, :bar, [], [file: 'file.ex', line: 10]}) == "(elixir) file.ex:10: Exception.bar()" assert Exception.format_stacktrace_entry({:lists, :bar, [1, 2, 3], []}) == "(stdlib) :lists.bar(1, 2, 3)" end test "format_stacktrace_entry with fun" do assert Exception.format_stacktrace_entry({fn(x) -> x end, [1], []}) =~ ~r/#Function<.+>\(1\)/ assert Exception.format_stacktrace_entry({fn(x, y) -> {x, y} end, 2, []}) =~ ~r"#Function<.+>/2" end test "format_mfa" do assert Exception.format_mfa(Foo, nil, 1) == "Foo.nil/1" assert Exception.format_mfa(Foo, :bar, 1) == "Foo.bar/1" assert Exception.format_mfa(Foo, :bar, []) == "Foo.bar()" assert Exception.format_mfa(nil, :bar, []) == "nil.bar()" assert Exception.format_mfa(:foo, :bar, [1, 2]) == ":foo.bar(1, 2)" assert Exception.format_mfa(Foo, :"bar baz", 1) == "Foo.\"bar baz\"/1" assert Exception.format_mfa(Foo, :"-func/2-fun-0-", 4) == "anonymous fn/4 in Foo.func/2" end test "format_fa" do assert Exception.format_fa(fn -> end, 1) =~ ~r"#Function<\d+\.\d+/0 in ExceptionTest\.test format_fa/1>/1" end ## Format exits test "format_exit" do assert Exception.format_exit(:bye) == ":bye" assert Exception.format_exit(:noconnection) == "no connection" assert Exception.format_exit({:nodedown, :"node@host"}) == "no connection to node@host" assert Exception.format_exit(:timeout) == "time out" assert Exception.format_exit(:noproc) == "no process" assert Exception.format_exit(:killed) == "killed" assert Exception.format_exit(:normal) == "normal" assert Exception.format_exit(:shutdown) == "shutdown" assert Exception.format_exit({:shutdown, :bye}) == "shutdown: :bye" assert Exception.format_exit({:badarg, [{:not_a_real_module, :function, 0, []}]}) == "an exception was raised:\n ** (ArgumentError) argument error\n :not_a_real_module.function/0" assert Exception.format_exit({:bad_call, :request}) == "bad call: :request" assert Exception.format_exit({:bad_cast, :request}) == "bad cast: :request" assert Exception.format_exit({:start_spec, :unexpected}) == "bad start spec: :unexpected" assert Exception.format_exit({:supervisor_data, :unexpected}) == "bad supervisor data: :unexpected" end defmodule Sup do def start_link(fun), do: :supervisor.start_link(__MODULE__, fun) def init(fun), do: fun.() end test "format_exit with supervisor errors" do trap = Process.flag(:trap_exit, true) {:error, reason} = __MODULE__.Sup.start_link(fn() -> :foo end) assert Exception.format_exit(reason) == "#{inspect(__MODULE__.Sup)}.init/1 returned a bad value: :foo" return = {:ok, {:foo, []}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad supervisor data: invalid type: :foo" return = {:ok, {{:foo, 1, 1}, []}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad supervisor data: invalid strategy: :foo" return = {:ok, {{:one_for_one, :foo, 1}, []}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad supervisor data: invalid intensity: :foo" return = {:ok, {{:one_for_one, 1, :foo}, []}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad supervisor data: invalid period: :foo" return = {:ok, {{:simple_one_for_one, 1, 1}, :foo}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid children: :foo" return = {:ok, {{:one_for_one, 1, 1}, [:foo]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid child spec: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, :foo, :temporary, 1, :worker, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid mfa: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {:m, :f, []}, :foo, 1, :worker, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid restart type: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {:m, :f, []}, :temporary, :foo, :worker, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid shutdown: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {:m, :f, []}, :temporary, 1, :foo, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid child type: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {:m, :f, []}, :temporary, 1, :worker, :foo}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid modules: :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {:m, :f, []}, :temporary, 1, :worker, [{:foo}]}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "bad start spec: invalid module: {:foo}" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {Kernel, :exit, [:foo]}, :temporary, 1, :worker, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "shutdown: failed to start child: :child\n ** (EXIT) :foo" return = {:ok, {{:one_for_one, 1, 1}, [{:child, {Kernel, :apply, [fn() -> {:error, :foo} end, []]}, :temporary, 1, :worker, []}]}} {:error, reason} = __MODULE__.Sup.start_link(fn() -> return end) assert Exception.format_exit(reason) == "shutdown: failed to start child: :child\n ** (EXIT) :foo" Process.flag(:trap_exit, trap) end test "format_exit with call" do reason = try do :gen_server.call(:does_not_exist, :hello) catch :exit, reason -> reason end assert Exception.format_exit(reason) == "exited in: :gen_server.call(:does_not_exist, :hello)\n ** (EXIT) no process" end test "format_exit with call with exception" do # Fake reason to prevent error_logger printing to stdout fsm_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]} reason = try do :gen_fsm.sync_send_event(spawn(fn() -> :timer.sleep(200) ; exit(fsm_reason) end), :hello) catch :exit, reason -> reason end formatted = Exception.format_exit(reason) assert formatted =~ ~r"exited in: :gen_fsm\.sync_send_event\(#PID<\d+\.\d+\.\d+>, :hello\)" assert formatted =~ ~r"\s{4}\*\* \(EXIT\) an exception was raised:\n" assert formatted =~ ~r"\s{8}\*\* \(ArgumentError\) argument error\n" assert formatted =~ ~r"\s{12}:not_a_real_module\.function/0" end test "format_exit with nested calls" do # Fake reason to prevent error_logger printing to stdout event_fun = fn() -> :timer.sleep(200) ; exit(:normal) end server_pid = spawn(fn()-> :gen_event.call(spawn(event_fun), :handler, :hello) end) reason = try do :gen_server.call(server_pid, :hi) catch :exit, reason -> reason end formatted = Exception.format_exit(reason) assert formatted =~ ~r"exited in: :gen_server\.call\(#PID<\d+\.\d+\.\d+>, :hi\)\n" assert formatted =~ ~r"\s{4}\*\* \(EXIT\) exited in: :gen_event\.call\(#PID<\d+\.\d+\.\d+>, :handler, :hello\)\n" assert formatted =~ ~r"\s{8}\*\* \(EXIT\) normal" end test "format_exit with nested calls and exception" do # Fake reason to prevent error_logger printing to stdout event_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]} event_fun = fn() -> :timer.sleep(200) ; exit(event_reason) end server_pid = spawn(fn()-> :gen_event.call(spawn(event_fun), :handler, :hello) end) reason = try do :gen_server.call(server_pid, :hi) catch :exit, reason -> reason end formatted = Exception.format_exit(reason) assert formatted =~ ~r"exited in: :gen_server\.call\(#PID<\d+\.\d+\.\d+>, :hi\)\n" assert formatted =~ ~r"\s{4}\*\* \(EXIT\) exited in: :gen_event\.call\(#PID<\d+\.\d+\.\d+>, :handler, :hello\)\n" assert formatted =~ ~r"\s{8}\*\* \(EXIT\) an exception was raised:\n" assert formatted =~ ~r"\s{12}\*\* \(ArgumentError\) argument error\n" assert formatted =~ ~r"\s{16}:not_a_real_module\.function/0" end ## Exception messagges import Exception, only: [message: 1] test "runtime error message" do assert %RuntimeError{} |> message == "runtime error" assert %RuntimeError{message: "exception"} |> message == "exception" end test "argument error message" do assert %ArgumentError{} |> message == "argument error" assert %ArgumentError{message: "exception"} |> message == "exception" end test "undefined function message" do assert %UndefinedFunctionError{} |> message == "undefined function" assert %UndefinedFunctionError{module: Kernel, function: :bar, arity: 1} |> message == "undefined function: Kernel.bar/1" assert %UndefinedFunctionError{module: Foo, function: :bar, arity: 1} |> message == "undefined function: Foo.bar/1 (module Foo is not available)" assert %UndefinedFunctionError{module: nil, function: :bar, arity: 0} |> message == "undefined function: nil.bar/0" end test "function clause message" do assert %FunctionClauseError{} |> message == "no function clause matches" assert %FunctionClauseError{module: Foo, function: :bar, arity: 1} |> message == "no function clause matching in Foo.bar/1" end test "erlang error message" do assert %ErlangError{original: :sample} |> message == "erlang error: :sample" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/file_test.exs000066400000000000000000001042141254730255300241330ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule Elixir.FileCase do use ExUnit.CaseTemplate import PathHelpers using do quote do import PathHelpers end end setup do File.mkdir_p!(tmp_path) on_exit(fn -> File.rm_rf(tmp_path) end) :ok end end defmodule FileTest do use Elixir.FileCase import Regex, only: [escape: 1] defmodule Cp do use Elixir.FileCase test :cp_with_src_file_and_dest_file do src = fixture_path("file.txt") dest = tmp_path("sample.txt") File.touch(dest) try do assert File.exists?(dest) assert File.cp(src, dest) == :ok assert File.exists?(dest) after File.rm(dest) end end test :cp_with_src_file_and_dest_dir do src = fixture_path("file.txt") dest = tmp_path("tmp") File.mkdir(dest) try do assert File.cp(src, dest) == {:error, :eisdir} after File.rm_rf dest end end test :cp_with_src_file_and_dest_unknown do src = fixture_path("file.txt") dest = tmp_path("tmp.file") try do refute File.exists?(dest) assert File.cp(src, dest) == :ok assert File.exists?(dest) after File.rm_rf dest end end test :cp_with_src_dir do src = fixture_path("cp_r") dest = tmp_path("tmp.file") assert File.cp(src, dest) == {:error, :eisdir} end test :cp_with_conflict do src = fixture_path("file.txt") dest = tmp_path("tmp.file") File.write!(dest, "hello") try do assert File.exists?(dest) assert File.cp(src, dest) == :ok assert File.read!(dest) == "FOO\n" after File.rm_rf dest end end test :cp_with_conflict_with_function do src = fixture_path("file.txt") dest = tmp_path("tmp.file") File.write!(dest, "hello") try do assert File.exists?(dest) assert File.cp(src, dest, fn(src_file, dest_file) -> assert src_file == src assert dest_file == dest false end) == :ok assert File.read!(dest) == "hello" after File.rm_rf dest end end test :cp_with_src_file_and_dest_file! do src = fixture_path("file.txt") dest = tmp_path("sample.txt") File.touch(dest) try do assert File.exists?(dest) assert File.cp!(src, dest) == :ok assert File.exists?(dest) after File.rm(dest) end end test :cp_with_src_dir! do src = fixture_path("cp_r") dest = tmp_path("tmp.file") assert_raise File.CopyError, "could not copy from #{src} to #{dest}: " <> "illegal operation on a directory", fn -> File.cp!(src, dest) end end test :copy_file_to_itself do src = dest = tmp_path("tmp.file") File.write!(src, "here") try do assert File.cp(src, dest) == :ok assert File.read!(dest) == "here" assert File.cp_r(src, dest) == {:ok, []} after File.rm(dest) end end test :cp_r_with_src_file_and_dest_file do src = fixture_path("file.txt") dest = tmp_path("sample.txt") File.touch(dest) try do assert File.exists?(dest) assert File.cp_r(src, dest) == {:ok, [dest]} assert File.exists?(dest) after File.rm(dest) end end test :cp_r_with_src_file_and_dest_dir do src = fixture_path("file.txt") dest = tmp_path("tmp") File.mkdir(dest) try do assert io_error? File.cp_r(src, dest) after File.rm_rf dest end end test :cp_r_with_src_file_and_dest_unknown do src = fixture_path("file.txt") dest = tmp_path("tmp.file") try do refute File.exists?(dest) assert File.cp_r(src, dest) == {:ok, [dest]} assert File.exists?(dest) after File.rm_rf dest end end test :cp_r_with_src_dir_and_dest_dir do src = fixture_path("cp_r") dest = tmp_path("tmp") File.mkdir(dest) try do refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) {:ok, files} = File.cp_r(src, dest) assert length(files) == 7 assert tmp_path("tmp/a") in files assert tmp_path("tmp/a/1.txt") in files assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) after File.rm_rf dest end end test :cp_r_with_src_dir_and_dest_file do src = fixture_path("cp_r") dest = tmp_path("tmp.file") try do File.touch!(dest) assert (File.cp_r(src, dest) |> io_error?) after File.rm_rf dest end end test :cp_r_with_src_dir_and_dest_unknown do src = fixture_path("cp_r") dest = tmp_path("tmp") try do refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) {:ok, files} = File.cp_r(src, dest) assert length(files) == 7 assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) after File.rm_rf dest end end test :cp_r_with_src_unknown do src = fixture_path("unknown") dest = tmp_path("tmp") assert File.cp_r(src, dest) == {:error, :enoent, src} end test :cp_r_with_dir_and_file_conflict do src = fixture_path("cp_r") dest = tmp_path("tmp") try do File.mkdir(dest) File.write!(Path.join(dest, "a"), "hello") assert io_error? File.cp_r(src, dest) after File.rm_rf dest end end test :cp_r_with_src_dir_and_dest_dir_using_lists do src = fixture_path("cp_r") |> to_char_list dest = tmp_path("tmp") |> to_char_list File.mkdir(dest) try do refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) {:ok, files} = File.cp_r(src, dest) assert length(files) == 7 assert Enum.all?(files, &is_binary/1) assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) after File.rm_rf dest end end test :cp_r_with_src_with_file_conflict do src = fixture_path("cp_r") dest = tmp_path("tmp") File.mkdir_p tmp_path("tmp/a") File.write! tmp_path("tmp/a/1.txt"), "hello" try do assert File.exists?(tmp_path("tmp/a/1.txt")) File.cp_r(src, dest) assert File.read!(tmp_path("tmp/a/1.txt")) == "" after File.rm_rf dest end end test :cp_r_with_src_with_file_conflict_callback do src = fixture_path("cp_r") dest = tmp_path("tmp") File.mkdir_p tmp_path("tmp/a") File.write! tmp_path("tmp/a/1.txt"), "hello" try do assert File.exists?(tmp_path("tmp/a/1.txt")) File.cp_r(src, dest, fn(src_file, dest_file) -> assert src_file == fixture_path("cp_r/a/1.txt") assert dest_file == tmp_path("tmp/a/1.txt") false end) assert File.read!(tmp_path("tmp/a/1.txt")) == "hello" after File.rm_rf dest end end test :cp_r! do src = fixture_path("cp_r") dest = tmp_path("tmp") File.mkdir(dest) try do refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) assert length(File.cp_r!(src, dest)) == 7 assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) after File.rm_rf dest end end test :cp_r_with_src_unknown! do src = fixture_path("unknown") dest = tmp_path("tmp") assert_raise File.CopyError, "could not copy recursively from #{src} to #{dest}. #{src}: no such file or directory", fn -> File.cp_r!(src, dest) end end test :cp_preserves_mode do File.mkdir_p!(tmp_path("tmp")) src = fixture_path("cp_mode") dest = tmp_path("tmp/cp_mode") File.cp!(src, dest) %File.Stat{mode: src_mode} = File.stat! src %File.Stat{mode: dest_mode} = File.stat! dest assert src_mode == dest_mode # On overwrite File.cp! src, dest, fn(_, _) -> true end %File.Stat{mode: src_mode} = File.stat! src %File.Stat{mode: dest_mode} = File.stat! dest assert src_mode == dest_mode end defp io_error?(result) do elem(result, 1) in [:enotdir, :eio, :enoent, :eisdir] end end defmodule Queries do use ExUnit.Case test :regular do assert File.regular?(__ENV__.file) assert File.regular?(String.to_char_list(__ENV__.file)) refute File.regular?("#{__ENV__.file}.unknown") end test :exists do assert File.exists?(__ENV__.file) assert File.exists?(fixture_path) assert File.exists?(fixture_path("file.txt")) refute File.exists?(fixture_path("missing.txt")) refute File.exists?("_missing.txt") end end test :ls do {:ok, value} = File.ls(fixture_path) assert "code_sample.exs" in value assert "file.txt" in value {:error, :enoent} = File.ls(fixture_path("non-existent-subdirectory")) end test :ls! do value = File.ls!(fixture_path) assert "code_sample.exs" in value assert "file.txt" in value assert_raise File.Error, fn -> File.ls!(fixture_path("non-existent-subdirectory")) end end defmodule OpenReadWrite do use Elixir.FileCase test :read_with_binary do assert {:ok, "FOO\n"} = File.read(fixture_path("file.txt")) assert {:error, :enoent} = File.read(fixture_path("missing.txt")) end test :read_with_list do assert {:ok, "FOO\n"} = File.read(Path.expand('fixtures/file.txt', __DIR__)) assert {:error, :enoent} = File.read(Path.expand('fixtures/missing.txt', __DIR__)) end test :read_with_utf8 do assert {:ok, "Русский\n日\n"} = File.read(Path.expand('fixtures/utf8.txt', __DIR__)) end test :read! do assert File.read!(fixture_path("file.txt")) == "FOO\n" expected_message = "could not read file fixtures/missing.txt: no such file or directory" assert_raise File.Error, expected_message, fn -> File.read!("fixtures/missing.txt") end end test :write_ascii_content do fixture = tmp_path("tmp_test.txt") try do refute File.exists?(fixture) assert File.write(fixture, 'test text') == :ok assert File.read(fixture) == {:ok, "test text"} after File.rm(fixture) end end test :write_utf8 do fixture = tmp_path("tmp_test.txt") try do refute File.exists?(fixture) assert File.write(fixture, "Русский\n日\n") == :ok assert {:ok, "Русский\n日\n"} == File.read(fixture) after File.rm(fixture) end end test :write_with_options do fixture = tmp_path("tmp_test.txt") try do refute File.exists?(fixture) assert File.write(fixture, "Русский\n日\n") == :ok assert File.write(fixture, "test text", [:append]) == :ok assert {:ok, "Русский\n日\ntest text"} == File.read(fixture) after File.rm(fixture) end end test :open_file_without_modes do {:ok, file} = File.open(fixture_path("file.txt")) assert IO.gets(file, "") == "FOO\n" assert File.close(file) == :ok end test :open_file_with_char_list do {:ok, file} = File.open(fixture_path("file.txt"), [:char_list]) assert IO.gets(file, "") == 'FOO\n' assert File.close(file) == :ok end test :open_utf8_by_default do {:ok, file} = File.open(fixture_path("utf8.txt"), [:utf8]) assert IO.gets(file, "") == "Русский\n" assert File.close(file) == :ok end test :open_readonly_by_default do {:ok, file} = File.open(fixture_path("file.txt")) assert_raise ArgumentError, fn -> IO.write(file, "foo") end assert File.close(file) == :ok end test :open_with_write_permission do fixture = tmp_path("tmp_text.txt") try do {:ok, file} = File.open(fixture, [:write]) assert IO.write(file, "foo") == :ok assert File.close(file) == :ok assert File.read(fixture) == {:ok, "foo"} after File.rm(fixture) end end test :open_with_binwrite_permission do fixture = tmp_path("tmp_text.txt") try do {:ok, file} = File.open(fixture, [:write]) assert IO.binwrite(file, "Русский") == :ok assert File.close(file) == :ok assert File.read(fixture) == {:ok, "Русский"} after File.rm(fixture) end end test :open_utf8_and_charlist do {:ok, file} = File.open(fixture_path("utf8.txt"), [:char_list, :utf8]) assert IO.gets(file, "") == [1056, 1091, 1089, 1089, 1082, 1080, 1081, 10] assert File.close(file) == :ok end test :open_respects_encoding do {:ok, file} = File.open(fixture_path("utf8.txt"), [{:encoding, :latin1}]) assert IO.gets(file, "") == <<195, 144, 194, 160, 195, 145, 194, 131, 195, 145, 194, 129, 195, 145, 194, 129, 195, 144, 194, 186, 195, 144, 194, 184, 195, 144, 194, 185, 10>> assert File.close(file) == :ok end test :open_a_missing_file do assert File.open('missing.txt') == {:error, :enoent} end test :open_a_file_with_function do file = fixture_path("file.txt") assert File.open(file, &IO.read(&1, :line)) == {:ok, "FOO\n"} end test :open_a_missing_file! do message = "could not open missing.txt: no such file or directory" assert_raise File.Error, message, fn -> File.open!('missing.txt') end end test :open_a_file_with_function! do file = fixture_path("file.txt") assert File.open!(file, &IO.read(&1, :line)) == "FOO\n" end end defmodule Mkdir do use Elixir.FileCase test :mkdir_with_binary do fixture = tmp_path("tmp_test") try do refute File.exists?(fixture) assert File.mkdir(fixture) == :ok assert File.exists?(fixture) after File.rmdir fixture end end test :mkdir_with_list do fixture = tmp_path("tmp_test") |> to_char_list try do refute File.exists?(fixture) assert File.mkdir(fixture) == :ok assert File.exists?(fixture) after File.rmdir fixture end end test :mkdir_with_invalid_path do fixture = fixture_path("file.txt") invalid = Path.join fixture, "test" assert File.exists?(fixture) assert io_error? File.mkdir(invalid) refute File.exists?(invalid) end test :mkdir! do fixture = tmp_path("tmp_test") try do refute File.exists?(fixture) assert File.mkdir!(fixture) == :ok assert File.exists?(fixture) after File.rmdir fixture end end test :mkdir_with_invalid_path! do fixture = fixture_path("file.txt") invalid = Path.join fixture, "test" assert File.exists?(fixture) assert_raise File.Error, ~r"^could not make directory #{escape invalid}: (not a directory|no such file or directory)", fn -> File.mkdir!(invalid) end end test :mkdir_p_with_one_directory do fixture = tmp_path("tmp_test") try do refute File.exists?(fixture) assert File.mkdir_p(fixture) == :ok assert File.exists?(fixture) after File.rm_rf fixture end end test :mkdir_p_with_nested_directory_and_binary do base = tmp_path("tmp_test") fixture = Path.join(base, "test") refute File.exists?(base) try do assert File.mkdir_p(fixture) == :ok assert File.exists?(base) assert File.exists?(fixture) after File.rm_rf base end end test :mkdir_p_with_nested_directory_and_list do base = tmp_path("tmp_test") |> to_char_list fixture = Path.join(base, "test") refute File.exists?(base) try do assert File.mkdir_p(fixture) == :ok assert File.exists?(base) assert File.exists?(fixture) after File.rm_rf base end end test :mkdir_p_with_nested_directory_and_existing_parent do base = tmp_path("tmp_test") fixture = Path.join(base, "test") File.mkdir(base) try do assert File.mkdir_p(fixture) == :ok assert File.exists?(base) assert File.exists?(fixture) after File.rm_rf base end end test :mkdir_p_with_invalid_path do assert File.exists?(fixture_path("file.txt")) invalid = Path.join fixture_path("file.txt"), "test/foo" assert io_error? File.mkdir(invalid) refute File.exists?(invalid) end test :mkdir_p! do fixture = tmp_path("tmp_test") try do refute File.exists?(fixture) assert File.mkdir_p!(fixture) == :ok assert File.exists?(fixture) after File.rm_rf fixture end end test :mkdir_p_with_invalid_path! do fixture = fixture_path("file.txt") invalid = Path.join fixture, "test" assert File.exists?(fixture) assert_raise File.Error, ~r"^could not make directory \(with -p\) #{escape invalid}: (not a directory|no such file or directory)", fn -> File.mkdir_p!(invalid) end end defp io_error?(result) do {:error, errorcode} = result errorcode in [:enotdir, :eio, :enoent, :eisdir] end end defmodule Rm do use Elixir.FileCase test :rm_file do fixture = tmp_path("tmp_test.txt") File.write(fixture, "test") assert File.exists?(fixture) assert File.rm(fixture) == :ok refute File.exists?(fixture) end test :rm_read_only_file do fixture = tmp_path("tmp_test.txt") File.write(fixture, "test") assert File.exists?(fixture) File.chmod(fixture, 0o100444) assert File.rm(fixture) == :ok refute File.exists?(fixture) end test :rm_file_with_dir do assert File.rm(fixture_path) == {:error, :eperm} end test :rm_nonexistent_file do assert File.rm('missing.txt') == {:error, :enoent} end test :rm! do fixture = tmp_path("tmp_test.txt") File.write(fixture, "test") assert File.exists?(fixture) assert File.rm!(fixture) == :ok refute File.exists?(fixture) end test :rm_with_invalid_file! do assert_raise File.Error, "could not remove file missing.file: no such file or directory", fn -> File.rm!("missing.file") end end test :rmdir do fixture = tmp_path("tmp_test") File.mkdir_p(fixture) assert File.dir?(fixture) assert File.rmdir(fixture) == :ok refute File.exists?(fixture) end test :rmdir_with_file do assert io_error? File.rmdir(fixture_path("file.txt")) end test :rmdir! do fixture = tmp_path("tmp_test") File.mkdir_p(fixture) assert File.dir?(fixture) assert File.rmdir!(fixture) == :ok refute File.exists?(fixture) end test :rmdir_with_file! do fixture = fixture_path("file.txt") assert_raise File.Error, ~r"^could not remove directory #{escape fixture}: (not a directory|I/O error)", fn -> File.rmdir!(fixture) end end test :rm_rf do fixture = tmp_path("tmp") File.mkdir(fixture) File.cp_r!(fixture_path("cp_r"), fixture) assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) {:ok, files} = File.rm_rf(fixture) assert length(files) == 7 assert fixture in files assert tmp_path("tmp/a/1.txt") in files refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) refute File.exists?(fixture) end test :rm_rf_with_symlink do from = tmp_path("tmp/from") to = tmp_path("tmp/to") File.mkdir_p!(to) File.write!(Path.join(to, "hello"), "world") :file.make_symlink(to, from) if File.exists?(from) or not windows? do assert File.exists?(from) {:ok, files} = File.rm_rf(from) assert length(files) == 1 assert File.exists?(Path.join(to, "hello")) refute File.exists?(from) end after File.rm(tmp_path("tmp/from")) end test :rm_rf_with_char_list do fixture = tmp_path("tmp") |> to_char_list File.mkdir(fixture) File.cp_r!(fixture_path("cp_r"), fixture) assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) {:ok, files} = File.rm_rf(fixture) assert length(files) == 7 assert tmp_path("tmp") in files assert Enum.all?(files, &is_binary/1) refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) refute File.exists?(fixture) end test :rm_rf_with_file do fixture = tmp_path("tmp") File.write(fixture, "hello") assert File.rm_rf(fixture) == {:ok, [fixture]} end test :rm_rf_with_unknown do fixture = tmp_path("tmp.unknown") assert File.rm_rf(fixture) == {:ok, []} end test :rm_rf_with_invalid do fixture = fixture_path "file.txt/path" assert File.rm_rf(fixture) == {:ok, []} end test :rm_rf! do fixture = tmp_path("tmp") File.mkdir(fixture) File.cp_r!(fixture_path("cp_r"), fixture) assert File.exists?(tmp_path("tmp/a/1.txt")) assert File.exists?(tmp_path("tmp/a/a/2.txt")) assert File.exists?(tmp_path("tmp/b/3.txt")) files = File.rm_rf!(fixture) assert length(files) == 7 assert fixture in files assert tmp_path("tmp/a/1.txt") in files refute File.exists?(tmp_path("tmp/a/1.txt")) refute File.exists?(tmp_path("tmp/a/a/2.txt")) refute File.exists?(tmp_path("tmp/b/3.txt")) refute File.exists?(fixture) end test :rm_rf_with_invalid! do fixture = fixture_path "file.txt/path" assert File.rm_rf!(fixture) == [] end defp io_error?(result) do elem(result, 1) in [:enotdir, :eio, :enoent, :eisdir] end end test :stat do {:ok, info} = File.stat(__ENV__.file) assert info.mtime end test :stat! do assert File.stat!(__ENV__.file).mtime end test :stat_with_invalid_file do assert {:error, _} = File.stat("./invalid_file") end test :stat_with_invalid_file! do assert_raise File.Error, fn -> File.stat!("./invalid_file") end end test :lstat do {:ok, info} = File.lstat(__ENV__.file) assert info.mtime end test :lstat! do assert File.lstat!(__ENV__.file).mtime end test :lstat_with_invalid_file do invalid_file = tmp_path("invalid_file") assert {:error, _} = File.lstat(invalid_file) end test :lstat_with_invalid_file! do invalid_file = tmp_path("invalid_file") assert_raise File.Error, fn -> File.lstat!(invalid_file) end end test :lstat_with_dangling_symlink do invalid_file = tmp_path("invalid_file") dest = tmp_path("dangling_symlink") File.ln_s(invalid_file, dest) try do assert {:ok, info } = File.lstat(dest) assert info.type == :symlink after File.rm(dest) end end test :lstat_with_dangling_symlink! do invalid_file = tmp_path("invalid_file") dest = tmp_path("dangling_symlink") File.ln_s(invalid_file, dest) try do assert File.lstat!(dest).type == :symlink after File.rm(dest) end end test :io_stream_utf8 do src = File.open! fixture_path("file.txt"), [:utf8] dest = tmp_path("tmp_test.txt") try do stream = IO.stream(src, :line) File.open dest, [:write], fn(target) -> Enum.into stream, IO.stream(target, :line), &String.replace(&1, "O", "A") end assert File.read(dest) == {:ok, "FAA\n"} after File.rm(dest) end end test :io_stream do src = File.open! fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do stream = IO.binstream(src, :line) File.open dest, [:write], fn(target) -> Enum.into stream, IO.binstream(target, :line), &String.replace(&1, "O", "A") end assert File.read(dest) == {:ok, "FAA\n"} after File.rm(dest) end end test :stream_map do src = fixture_path("file.txt") stream = File.stream!(src) assert %File.Stream{} = stream assert stream.modes == [:raw, :read_ahead, :binary] assert stream.raw assert stream.line_or_bytes == :line src = fixture_path("file.txt") stream = File.stream!(src, [:utf8], 10) assert %File.Stream{} = stream assert stream.modes == [{:encoding, :utf8}, :binary] refute stream.raw assert stream.line_or_bytes == 10 end test :stream_line_utf8 do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do stream = File.stream!(src) File.open dest, [:write, :utf8], fn(target) -> Enum.each stream, fn(line) -> IO.write target, String.replace(line, "O", "A") end end assert File.read(dest) == {:ok, "FAA\n"} after File.rm(dest) end end test :stream_bytes_utf8 do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do stream = File.stream!(src, [:utf8], 1) File.open dest, [:write], fn(target) -> Enum.each stream, fn(line) -> IO.write target, String.replace(line, "OO", "AA") end end assert File.read(dest) == {:ok, "FOO\n"} after File.rm(dest) end end test :stream_line do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do stream = File.stream!(src) File.open dest, [:write], fn(target) -> Enum.each stream, fn(line) -> IO.write target, String.replace(line, "O", "A") end end assert File.read(dest) == {:ok, "FAA\n"} after File.rm(dest) end end test :stream_bytes do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do stream = File.stream!(src, [], 1) File.open dest, [:write], fn(target) -> Enum.each stream, fn(line) -> IO.write target, String.replace(line, "OO", "AA") end end assert File.read(dest) == {:ok, "FOO\n"} after File.rm(dest) end end test :stream_into do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) original = File.stream!(dest) stream = File.stream!(src) |> Stream.map(&String.replace(&1, "O", "A")) |> Enum.into(original) assert stream == original assert File.read(dest) == {:ok, "FAA\n"} after File.rm(dest) end end test :stream_into_append do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) original = File.stream!(dest, [:append]) File.stream!(src, [:append]) |> Stream.map(&String.replace(&1, "O", "A")) |> Enum.into(original) File.stream!(src, [:append]) |> Enum.into(original) assert File.read(dest) == {:ok, "FAA\nFOO\n"} after File.rm(dest) end end test :ln_s do existing = fixture_path("file.txt") new = tmp_path("tmp_test.txt") try do refute File.exists?(new) assert File.ln_s(existing, new) == :ok assert File.read(new) == {:ok, "FOO\n"} after File.rm(new) end end test :ln_s_with_existing_destination do existing = fixture_path("file.txt") assert File.ln_s(existing, existing) == {:error, :eexist} end test :copy do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) assert File.copy(src, dest) == {:ok, 4} assert File.read(dest) == {:ok, "FOO\n"} after File.rm(dest) end end test :copy_with_bytes_count do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) assert File.copy(src, dest, 2) == {:ok, 2} assert {:ok, "FO"} == File.read(dest) after File.rm(dest) end end test :copy_with_invalid_file do src = fixture_path("invalid.txt") dest = tmp_path("tmp_test.txt") assert File.copy(src, dest, 2) == {:error, :enoent} end test :copy! do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) assert File.copy!(src, dest) == 4 assert {:ok, "FOO\n"} == File.read(dest) after File.rm(dest) end end test :copy_with_bytes_count! do src = fixture_path("file.txt") dest = tmp_path("tmp_test.txt") try do refute File.exists?(dest) assert File.copy!(src, dest, 2) == 2 assert {:ok, "FO"} == File.read(dest) after File.rm(dest) end end test :copy_with_invalid_file! do src = fixture_path("invalid.txt") dest = tmp_path("tmp_test.txt") assert_raise File.CopyError, "could not copy from #{src} to #{dest}: no such file or directory", fn -> File.copy!(src, dest, 2) end end test :cwd_and_cd do {:ok, current} = File.cwd try do assert File.cd(fixture_path) == :ok assert File.exists?("file.txt") after File.cd!(current) end end if :file.native_name_encoding == :utf8 do test :cwd_and_cd_with_utf8 do File.mkdir_p(tmp_path("héllò")) File.cd!(tmp_path("héllò"), fn -> assert Path.basename(File.cwd!) == "héllò" end) after File.rm_rf tmp_path("héllò") end end test :invalid_cd do assert io_error? File.cd(fixture_path("file.txt")) end test :invalid_cd! do message = ~r"^could not set current working directory to #{escape fixture_path("file.txt")}: (not a directory|no such file or directory)" assert_raise File.Error, message, fn -> File.cd!(fixture_path("file.txt")) end end test :cd_with_function do assert File.cd!(fixture_path, fn -> assert File.exists?("file.txt") :cd_result end) == :cd_result end test :touch_with_no_file do fixture = tmp_path("tmp_test.txt") time = {{2010, 4, 17}, {14, 0, 0}} try do refute File.exists?(fixture) assert File.touch(fixture, time) == :ok assert {:ok, ""} == File.read(fixture) assert File.stat!(fixture).mtime == time after File.rm(fixture) end end test :touch_with_timestamp do fixture = tmp_path("tmp_test.txt") try do assert File.touch!(fixture) == :ok stat = File.stat!(fixture) assert File.touch!(fixture, last_year) == :ok assert stat.mtime > File.stat!(fixture).mtime after File.rm(fixture) end end test :touch_with_dir do assert File.touch(fixture_path) == :ok end test :touch_with_failure do fixture = fixture_path("file.txt/bar") assert io_error? File.touch(fixture) end test :touch_with_success! do assert File.touch!(fixture_path) == :ok end test :touch_with_failure! do fixture = fixture_path("file.txt/bar") assert_raise File.Error, ~r"could not touch #{escape fixture}: (not a directory|no such file or directory)", fn -> File.touch!(fixture) end end test :chmod_with_success do fixture = tmp_path("tmp_test.txt") File.touch(fixture) try do assert File.chmod(fixture, 0o100666) == :ok stat = File.stat!(fixture) assert stat.mode == 0o100666 unless windows? do assert File.chmod(fixture, 0o100777) == :ok stat = File.stat!(fixture) assert stat.mode == 0o100777 end after File.rm(fixture) end end test :chmod_with_success! do fixture = tmp_path("tmp_test.txt") File.touch(fixture) try do assert File.chmod!(fixture, 0o100666) == :ok stat = File.stat!(fixture) assert stat.mode == 0o100666 unless windows? do assert File.chmod!(fixture, 0o100777) == :ok stat = File.stat!(fixture) assert stat.mode == 0o100777 end after File.rm(fixture) end end test :chmod_with_failure do fixture = tmp_path("tmp_test.txt") File.rm(fixture) assert File.chmod(fixture, 0o100777) == {:error, :enoent} end test :chmod_with_failure! do fixture = tmp_path("tmp_test.txt") File.rm(fixture) message = ~r"could not change mode for #{escape fixture}: no such file or directory" assert_raise File.Error, message, fn -> File.chmod!(fixture, 0o100777) end end test :chgrp_with_failure do fixture = tmp_path("tmp_test.txt") File.rm(fixture) assert File.chgrp(fixture, 1) == {:error, :enoent} end test :chgrp_with_failure! do fixture = tmp_path("tmp_test.txt") File.rm(fixture) message = ~r"could not change group for #{escape fixture}: no such file or directory" assert_raise File.Error, message, fn -> File.chgrp!(fixture, 1) end end test :chown_with_failure do fixture = tmp_path("tmp_test.txt") File.rm(fixture) assert File.chown(fixture, 1) == {:error, :enoent} end test :chown_with_failure! do fixture = tmp_path("tmp_test.txt") File.rm(fixture) message = ~r"could not change owner for #{escape fixture}: no such file or directory" assert_raise File.Error, message, fn -> File.chown!(fixture, 1) end end defp last_year do last_year :calendar.local_time end defp last_year({{year, month, day}, time}) do {{year - 1, month, day}, time} end defp io_error?(result) do {:error, errorcode} = result errorcode in [:enotdir, :eio, :enoent, :eisdir] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/000077500000000000000000000000001254730255300233035ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/at_exit.exs000066400000000000000000000003371254730255300254640ustar00rootroot00000000000000defmodule AtExit do def at_exit(str) do System.at_exit fn(_) -> IO.write(str) end end end System.at_exit fn(status) -> IO.puts "cruel world with status #{status}" end AtExit.at_exit("goodbye ") exit({:shutdown, 1}) elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/code_sample.exs000066400000000000000000000000371254730255300262770ustar00rootroot00000000000000# Some Comments var = 1 + 2 varelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/compile_sample.ex000066400000000000000000000000411254730255300266250ustar00rootroot00000000000000defmodule CompileSample, do: nil elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_mode000077500000000000000000000000001254730255300246250ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/000077500000000000000000000000001254730255300242265ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/a/000077500000000000000000000000001254730255300244465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/a/1.txt000066400000000000000000000000001254730255300253350ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/a/a/000077500000000000000000000000001254730255300246665ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/a/a/2.txt000066400000000000000000000000001254730255300255560ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/b/000077500000000000000000000000001254730255300244475ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/cp_r/b/3.txt000066400000000000000000000000001254730255300253400ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/file.bin000066400000000000000000000000221254730255300247060ustar00rootroot00000000000000LF CR CRLF LFCR elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/file.txt000066400000000000000000000000041254730255300247550ustar00rootroot00000000000000FOO elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/init_sample.exs000066400000000000000000000000301254730255300263210ustar00rootroot00000000000000IO.puts to_string(1 + 2)elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_compiler/000077500000000000000000000000001254730255300267715ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_compiler/bar.ex000066400000000000000000000000651254730255300300740ustar00rootroot00000000000000defmodule Bar do end require Foo IO.puts Foo.messageelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_compiler/bat.ex000066400000000000000000000000671254730255300301000ustar00rootroot00000000000000defmodule Bat do ThisModuleWillNeverBeAvailable[] endelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_compiler/foo.ex000066400000000000000000000000721254730255300301110ustar00rootroot00000000000000defmodule Foo do def message, do: "message_from_foo" endelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_deadlock/000077500000000000000000000000001254730255300267255ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_deadlock/bar.ex000066400000000000000000000000541254730255300300260ustar00rootroot00000000000000defmodule Bar do Foo.__info__(:macros) endelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_deadlock/foo.ex000066400000000000000000000000541254730255300300450ustar00rootroot00000000000000defmodule Foo do Bar.__info__(:macros) endelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_struct/000077500000000000000000000000001254730255300265035ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_struct/bar.ex000066400000000000000000000001071254730255300276030ustar00rootroot00000000000000defmodule Bar do defstruct name: "" def foo?(%Foo{}), do: true end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/parallel_struct/foo.ex000066400000000000000000000001071254730255300276220ustar00rootroot00000000000000defmodule Foo do defstruct name: "" def bar?(%Bar{}), do: true end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/utf8.txt000066400000000000000000000000231254730255300247250ustar00rootroot00000000000000Русский 日 elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/fixtures/warnings_sample.ex000066400000000000000000000001141254730255300270260ustar00rootroot00000000000000defmodule WarningsSample do def hello(a), do: a def hello(b), do: b end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/float_test.exs000066400000000000000000000062361254730255300243260ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule FloatTest do use ExUnit.Case, async: true test :parse do assert Float.parse("12") === {12.0, ""} assert Float.parse("-12") === {-12.0, ""} assert Float.parse("-0.1") === {-0.1, ""} assert Float.parse("123456789") === {123456789.0, ""} assert Float.parse("12.5") === {12.5, ""} assert Float.parse("12.524235") === {12.524235, ""} assert Float.parse("-12.5") === {-12.5, ""} assert Float.parse("-12.524235") === {-12.524235, ""} assert Float.parse("0.3534091") === {0.3534091, ""} assert Float.parse("0.3534091elixir") === {0.3534091, "elixir"} assert Float.parse("7.5e3") === {7.5e3, ""} assert Float.parse("7.5e-3") === {7.5e-3, ""} assert Float.parse("12x") === {12.0, "x"} assert Float.parse("12.5x") === {12.5, "x"} assert Float.parse("-12.32453e10") === {-1.232453e11, ""} assert Float.parse("-12.32453e-10") === {-1.232453e-9, ""} assert Float.parse("0.32453e-10") === {3.2453e-11, ""} assert Float.parse("1.32453e-10") === {1.32453e-10, ""} assert Float.parse("1.32.45") === {1.32, ".45"} assert Float.parse("1.o") === {1.0, ".o"} assert Float.parse("--1.2") === :error assert Float.parse("++1.2") === :error assert Float.parse("pi") === :error end test :floor do assert Float.floor(12.524235) === 12.0 assert Float.floor(-12.5) === -13.0 assert Float.floor(-12.524235) === -13.0 assert Float.floor(7.5e3) === 7500.0 assert Float.floor(7.5432e3) === 7543.0 assert Float.floor(7.5e-3) === 0.0 assert Float.floor(-12.32453e4) === -123246.0 assert Float.floor(-12.32453e-10) === -1.0 assert Float.floor(0.32453e-10) === 0.0 assert Float.floor(-0.32453e-10) === -1.0 assert Float.floor(1.32453e-10) === 0.0 end test :floor_with_precision do assert Float.floor(12.524235, 0) === 12.0 assert Float.floor(-12.524235, 0) === -13.0 assert Float.floor(12.52, 2) === 12.52 assert Float.floor(-12.52, 2) === -12.52 assert Float.floor(12.524235, 2) === 12.52 assert Float.floor(-12.524235, 3) === -12.525 end test :ceil do assert Float.ceil(12.524235) === 13.0 assert Float.ceil(-12.5) === -12.0 assert Float.ceil(-12.524235) === -12.0 assert Float.ceil(7.5e3) === 7500.0 assert Float.ceil(7.5432e3) === 7544.0 assert Float.ceil(7.5e-3) === 1.0 assert Float.ceil(-12.32453e4) === -123245.0 assert Float.ceil(-12.32453e-10) === 0.0 assert Float.ceil(0.32453e-10) === 1.0 assert Float.ceil(-0.32453e-10) === 0.0 assert Float.ceil(1.32453e-10) === 1.0 end test :ceil_with_precision do assert Float.ceil(12.524235, 0) === 13.0 assert Float.ceil(-12.524235, 0) === -12.0 assert Float.ceil(12.52, 2) === 12.52 assert Float.ceil(-12.52, 2) === -12.52 assert Float.ceil(12.524235, 2) === 12.53 assert Float.ceil(-12.524235, 3) === -12.524 end test :round do assert Float.round(5.5675, 3) === 5.568 assert Float.round(-5.5674, 3) === -5.567 assert Float.round(5.5, 3) === 5.5 assert Float.round(5.5e-10, 10) === 6.0e-10 assert Float.round(5.5e-10, 8) === 0.0 assert Float.round(5.0, 0) === 5.0 end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/gen_event/000077500000000000000000000000001254730255300234045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/gen_event/stream_test.exs000066400000000000000000000161611254730255300264640ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule GenEvent.StreamTest do use ExUnit.Case, async: true defmodule SlowHandler do use GenEvent def handle_event(_event, _state) do :timer.sleep(100) :remove_handler end end defp notify(:async, manager, event), do: GenEvent.notify(manager, event) defp notify(:sync, manager, event), do: GenEvent.sync_notify(manager, event) defp notify(:ack, manager, event), do: GenEvent.ack_notify(manager, event) @receive_timeout 1000 test "ack stream/2" do {:ok, pid} = GenEvent.start_link() parent = self() spawn_link fn -> send parent, Enum.take(GenEvent.stream(pid), 3) end wait_for_handlers(pid, 1) for i <- 1..3 do GenEvent.ack_notify(pid, i) end assert_receive [1, 2, 3], @receive_timeout wait_for_handlers(pid, 0) spawn_link fn -> Enum.each GenEvent.stream(pid), fn _ -> :timer.sleep(:infinity) end end wait_for_handlers(pid, 1) for i <- 1..6 do spawn_link fn -> GenEvent.ack_notify(pid, i) end end # Note the length is 4 compared to 5 n the sync case. wait_for_queue_length(pid, 4) end test "sync stream/2" do {:ok, pid} = GenEvent.start_link() parent = self() spawn_link fn -> send parent, Enum.take(GenEvent.stream(pid), 3) end wait_for_handlers(pid, 1) for i <- 1..3 do GenEvent.sync_notify(pid, i) end assert_receive [1, 2, 3], @receive_timeout wait_for_handlers(pid, 0) spawn_link fn -> Enum.each GenEvent.stream(pid), fn _ -> :timer.sleep(:infinity) end end wait_for_handlers(pid, 1) for i <- 1..6 do spawn_link fn -> GenEvent.sync_notify(pid, i) end end wait_for_queue_length(pid, 5) end test "async stream/2" do {:ok, pid} = GenEvent.start_link() parent = self() spawn_link fn -> Enum.each(GenEvent.stream(pid), fn _ -> :timer.sleep(:infinity) end) end spawn_link fn -> send parent, Enum.take(GenEvent.stream(pid), 3) end wait_for_handlers(pid, 2) for i <- 1..3 do GenEvent.notify(pid, i) end assert_receive [1, 2, 3], @receive_timeout wait_for_handlers(pid, 1) end test "stream/2 with timeout" do {:ok, pid} = GenEvent.start_link() Process.flag(:trap_exit, true) child = spawn_link fn -> Enum.take(GenEvent.stream(pid, timeout: 50), 5) end assert_receive {:EXIT, ^child, {:timeout, {Enumerable.GenEvent.Stream, :next, [_, _]}}}, @receive_timeout end test "stream/2 with error/timeout on subscription" do {:ok, pid} = GenEvent.start_link() child = spawn fn -> Enum.to_list(GenEvent.stream(pid)) end wait_for_handlers(pid, 1) Process.exit(child, :kill) wait_for_handlers(pid, 0) GenEvent.stop(pid) end test "stream/2 with manager killed and trap_exit" do {:ok, pid} = GenEvent.start_link() stream = GenEvent.stream(pid) parent = self() child = spawn_link fn -> send parent, Enum.to_list(stream) end wait_for_handlers(pid, 1) Process.flag(:trap_exit, true) Process.exit(pid, :kill) assert_receive {:EXIT, ^pid, :killed}, @receive_timeout assert_receive ({:EXIT, ^child, {stat, {Enumerable.GenEvent.Stream, :stop, [_, _]}}} when stat in [:killed, :noproc]), @receive_timeout end test "stream/2 with manager not alive" do stream = GenEvent.stream(:does_not_exit) parent = self() Process.flag(:trap_exit, true) child = spawn_link fn -> send parent, Enum.to_list(stream) end assert_receive {:EXIT, ^child, {:noproc, {Enumerable.GenEvent.Stream, :start, [_]}}}, @receive_timeout end Enum.each [:sync, :async, :ack], fn mode -> @mode mode test "#{mode} stream/2 with parallel use (and first finishing first)" do {:ok, pid} = GenEvent.start_link() stream = GenEvent.stream(pid) parent = self() spawn_link fn -> send parent, {:take3, Enum.take(stream, 3)} end wait_for_handlers(pid, 1) spawn_link fn -> send parent, {:take5, Enum.take(stream, 5)} end wait_for_handlers(pid, 2) # Notify the events for both handlers for i <- 1..3 do notify(@mode, pid, i) end assert_receive {:take3, [1, 2, 3]}, @receive_timeout # Notify the events for to_list stream handler for i <- 4..5 do notify(@mode, pid, i) end assert_receive {:take5, [1, 2, 3, 4, 5]}, @receive_timeout end test "#{mode} stream/2 with manager stop" do {:ok, pid} = GenEvent.start_link() parent = self() child = spawn_link fn -> send parent, Enum.take(GenEvent.stream(pid), 5) end wait_for_handlers(pid, 1) for i <- 1..3 do notify(@mode, pid, i) end Process.flag(:trap_exit, true) GenEvent.stop(pid) assert_receive {:EXIT, ^child, :normal}, @receive_timeout end test "#{mode} stream/2 with swap_handler" do {:ok, pid} = GenEvent.start_link() stream = GenEvent.stream(pid, id: make_ref()) parent = self() spawn_link(fn -> send parent, Enum.take(stream, 5) end) wait_for_handlers(pid, 1) for i <- 1..3 do notify(@mode, pid, i) end [handler] = GenEvent.which_handlers(pid) GenEvent.swap_handler(pid, handler, :swap_handler, UnknownHandler, []) assert_receive [1, 2, 3], @receive_timeout end test "#{mode} stream/2 with manager unregistered" do {:ok, pid} = GenEvent.start_link(name: :unreg) stream = GenEvent.stream(:unreg) parent = self() spawn_link fn -> send parent, Enum.take(stream, 5) end wait_for_handlers(pid, 1) # Notify the events for i <- 1..3 do notify(@mode, pid, i) end # Unregister the process Process.unregister(:unreg) # Notify the remaining events for i <- 4..5 do notify(@mode, pid, i) end # We should have gotten the message and all handlers were removed assert_receive [1, 2, 3, 4, 5], @receive_timeout wait_for_handlers(pid, 0) end test "#{mode} stream/2 flushes events on abort" do {:ok, pid} = GenEvent.start_link() spawn_link fn -> wait_for_handlers(pid, 2) notify(@mode, pid, 1) notify(@mode, pid, 2) notify(@mode, pid, 3) end GenEvent.add_handler(pid, SlowHandler, []) stream = GenEvent.stream(pid) try do Enum.each stream, fn _ -> throw :done end catch :done -> :ok end # Wait for the slow handler to be removed # so all events have been handled wait_for_handlers(pid, 0) # Check no messages leaked. refute_received _any end end defp wait_for_handlers(pid, count) do unless length(GenEvent.which_handlers(pid)) == count do wait_for_handlers(pid, count) end end defp wait_for_queue_length(pid, count) do {:message_queue_len, n} = Process.info(pid, :message_queue_len) unless n == count do wait_for_queue_length(pid, count) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/gen_event_test.exs000066400000000000000000000405161254730255300251720ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule GenEventTest do use ExUnit.Case defmodule ReplyHandler do use GenEvent def init(:raise) do raise "oops" end def init({:throw, process}) do {:ok, process} end def init({:raise, _}) do raise "oops" end def init({:swap, {:error, :not_found}}) do {:error, :not_found_on_swap} end def init({:swap, parent}) when is_pid(parent) do send parent, :swapped {:ok, parent} end def init({:custom, return}) do return end def init({parent, :hibernate}) do {:ok, parent, :hibernate} end def init({parent, trap}) when is_pid(parent) and is_boolean(trap) do Process.flag(:trap_exit, trap) {:ok, parent} end def handle_event(:raise, _parent) do raise "oops" end def handle_event(:hibernate, parent) do {:ok, parent, :hibernate} end def handle_event({:custom, reply}, _parent) do reply end def handle_event(event, parent) do send parent, {:event, event} {:ok, parent} end def handle_call(:raise, _parent) do raise "oops" end def handle_call(:hibernate, parent) do {:ok, :ok, parent, :hibernate} end def handle_call({:custom, reply}, _parent) do reply end def handle_call(event, parent) do send parent, {:call, event} {:ok, :ok, parent} end def handle_info(:hibernate, parent) do {:ok, parent, :hibernate} end def handle_info(event, parent) do send parent, {:info, event} {:ok, parent} end def terminate(:raise, _parent) do raise "oops" end def terminate(:swapped, parent) do send parent, {:terminate, :swapped} parent end def terminate(arg, parent) do send parent, {:terminate, arg} end end defmodule DefaultHandler do use GenEvent end defmodule Via do def register_name(name, pid) do Process.register(pid, name) :yes end def whereis_name(name) do Process.whereis(name) || :undefined end end @receive_timeout 1000 test "start/1" do assert {:ok, pid} = GenEvent.start() assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop(pid) == :ok assert {:ok, pid} = GenEvent.start(name: :my_gen_event_name) assert GenEvent.which_handlers(:my_gen_event_name) == [] assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop(:my_gen_event_name) == :ok end test "start_link/1" do assert {:ok, pid} = GenEvent.start_link() assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop(pid) == :ok assert {:ok, pid} = GenEvent.start_link(name: :my_gen_event_name) assert GenEvent.which_handlers(:my_gen_event_name) == [] assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop(:my_gen_event_name) == :ok assert {:ok, pid} = GenEvent.start_link(name: {:global, :my_gen_event_name}) assert GenEvent.which_handlers({:global, :my_gen_event_name}) == [] assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop({:global, :my_gen_event_name}) == :ok assert {:ok, pid} = GenEvent.start_link(name: {:via, Via, :my_gen_event_name}) assert GenEvent.which_handlers({:via, Via, :my_gen_event_name}) == [] assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop({:via, Via, :my_gen_event_name}) == :ok assert {:ok, pid} = GenEvent.start_link(name: :my_gen_event_name) assert GenEvent.start_link(name: :my_gen_event_name) == {:error, {:already_started, pid}} assert GenEvent.stop(pid) == :ok end test "handles exit signals" do Process.flag(:trap_exit, true) # Terminates on signal from parent when not trapping exits {:ok, pid} = GenEvent.start_link() :ok = GenEvent.add_handler(pid, ReplyHandler, {self(), false}) Process.exit(pid, :shutdown) assert_receive {:EXIT, ^pid, :shutdown} refute_received {:terminate, _} # Terminates on signal from parent when trapping exits {:ok, pid} = GenEvent.start_link() :ok = GenEvent.add_handler(pid, ReplyHandler, {self(), true}) Process.exit(pid, :shutdown) assert_receive {:EXIT, ^pid, :shutdown} assert_receive {:terminate, :stop} # Terminates on signal not from parent when not trapping exits {:ok, pid} = GenEvent.start_link() :ok = GenEvent.add_handler(pid, ReplyHandler, {self(), false}) spawn fn -> Process.exit(pid, :shutdown) end assert_receive {:EXIT, ^pid, :shutdown} refute_received {:terminate, _} # Does not terminate on signal not from parent when trapping exits {:ok, pid} = GenEvent.start_link() :ok = GenEvent.add_handler(pid, ReplyHandler, {self(), true}) terminator = spawn fn -> Process.exit(pid, :shutdown) end assert_receive {:info, {:EXIT, ^terminator, :shutdown}} refute_received {:terminate, _} end test "hibernates" do {:ok, pid} = GenEvent.start() :ok = GenEvent.add_handler(pid, ReplyHandler, {self(), :hibernate}) wait_until fn -> hibernating?(pid) end wake_up(pid) refute hibernating?(pid) :ok = GenEvent.call(pid, ReplyHandler, :hibernate) wait_until fn -> hibernating?(pid) end wake_up(pid) :ok = GenEvent.sync_notify(pid, :hibernate) wait_until fn -> hibernating?(pid) end GenEvent.stop(pid) end test "add_handler/3" do {:ok, pid} = GenEvent.start() assert GenEvent.add_handler(pid, ReplyHandler, {:custom, {:error, :my_error}}) == {:error, :my_error} assert GenEvent.add_handler(pid, ReplyHandler, {:custom, :oops}) == {:error, {:bad_return_value, :oops}} assert {:error, {%RuntimeError{}, _}} = GenEvent.add_handler(pid, ReplyHandler, :raise) assert GenEvent.add_handler(pid, ReplyHandler, {:throw, self()}) == :ok assert GenEvent.which_handlers(pid) == [ReplyHandler] assert GenEvent.add_handler(pid, ReplyHandler, {:throw, self()}) == {:error, :already_present} assert GenEvent.add_handler(pid, {ReplyHandler, self()}, {self(), false}) == :ok assert GenEvent.which_handlers(pid) == [{ReplyHandler, self()}, ReplyHandler] end test "add_mon_handler/3" do {:ok, pid} = GenEvent.start() parent = self() {mon_pid, mon_ref} = spawn_monitor(fn -> assert GenEvent.add_mon_handler(pid, ReplyHandler, {self(), false}) == :ok send parent, :ok receive after: (:infinity -> :ok) end) assert_receive :ok assert GenEvent.add_handler(pid, {ReplyHandler, self()}, {self(), false}) == :ok assert GenEvent.which_handlers(pid) == [{ReplyHandler, self()}, ReplyHandler] # A regular monitor message is passed forward send pid, {:DOWN, make_ref(), :process, self(), :oops} assert_receive {:info, {:DOWN, _, :process, _, :oops}} # Killing the monitor though is not passed forward Process.exit(mon_pid, :oops) assert_receive {:DOWN, ^mon_ref, :process, ^mon_pid, :oops} refute_received {:info, {:DOWN, _, :process, _, :oops}} assert GenEvent.which_handlers(pid) == [{ReplyHandler, self()}] end test "add_mon_handler/3 with notifications" do {:ok, pid} = GenEvent.start() self = self() GenEvent.add_mon_handler(pid, ReplyHandler, {self(), false}) GenEvent.remove_handler(pid, ReplyHandler, :ok) assert_receive {:gen_event_EXIT, ReplyHandler, :normal} :ok = GenEvent.add_mon_handler(pid, ReplyHandler, {self(), false}) :ok = GenEvent.swap_handler(pid, ReplyHandler, :swapped, ReplyHandler, :swap) assert_receive {:gen_event_EXIT, ReplyHandler, {:swapped, ReplyHandler, nil}} :ok = GenEvent.swap_mon_handler(pid, ReplyHandler, :swapped, ReplyHandler, :swap) :ok = GenEvent.swap_mon_handler(pid, ReplyHandler, :swapped, ReplyHandler, :swap) assert_receive {:gen_event_EXIT, ReplyHandler, {:swapped, ReplyHandler, ^self}} GenEvent.stop(pid) assert_receive {:gen_event_EXIT, ReplyHandler, :shutdown} end test "remove_handler/3" do {:ok, pid} = GenEvent.start() GenEvent.add_mon_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.remove_handler(pid, {ReplyHandler, self()}, :ok) == {:error, :not_found} assert GenEvent.remove_handler(pid, ReplyHandler, :ok) == {:terminate, :ok} assert_receive {:terminate, :ok} GenEvent.add_mon_handler(pid, {ReplyHandler, self()}, {self(), false}) assert GenEvent.remove_handler(pid, ReplyHandler, :ok) == {:error, :not_found} assert {:error, {%RuntimeError{}, _}} = GenEvent.remove_handler(pid, {ReplyHandler, self()}, :raise) assert GenEvent.which_handlers(pid) == [] end test "swap_handler/5" do {:ok, pid} = GenEvent.start() GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.swap_handler(pid, ReplyHandler, :swapped, {ReplyHandler, self()}, :swap) == :ok assert_receive {:terminate, :swapped} assert_receive :swapped assert GenEvent.add_handler(pid, ReplyHandler, {self(), false}) == :ok assert GenEvent.swap_handler(pid, ReplyHandler, :swapped, {ReplyHandler, self()}, :swap) == {:error, :already_present} assert GenEvent.which_handlers(pid) == [{ReplyHandler, self()}] assert GenEvent.remove_handler(pid, {ReplyHandler, self()}, :remove_handler) == {:terminate, :remove_handler} # The handler is initialized even when the module does not exist # on swap. However, in this case, we are returning an error on init. assert GenEvent.swap_handler(pid, ReplyHandler, :swapped, ReplyHandler, :swap) == {:error, :not_found_on_swap} end test "notify/2" do {:ok, pid} = GenEvent.start() GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.notify(pid, :hello) == :ok assert_receive {:event, :hello} assert GenEvent.notify(pid, {:custom, :remove_handler}) == :ok assert_receive {:terminate, :remove_handler} assert GenEvent.which_handlers(pid) == [] Logger.remove_backend(:console) GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.notify(pid, {:custom, :oops}) == :ok assert_receive {:terminate, {:error, {:bad_return_value, :oops}}} GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.notify(pid, :raise) == :ok assert_receive {:terminate, {:error, {%RuntimeError{}, _}}} after Logger.add_backend(:console, flush: true) end test "notify/2 with bad args" do assert GenEvent.notify({:global, :foo}, :bar) == :ok assert GenEvent.notify({:foo, :bar}, :bar) == :ok assert GenEvent.notify(self, :bar) == :ok assert_raise ArgumentError, fn -> GenEvent.notify(:foo, :bar) end end test "ack_notify/2" do {:ok, pid} = GenEvent.start() GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.ack_notify(pid, :hello) == :ok assert_receive {:event, :hello} assert GenEvent.ack_notify(pid, {:custom, :remove_handler}) == :ok assert_receive {:terminate, :remove_handler} assert GenEvent.which_handlers(pid) == [] Logger.remove_backend(:console) GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.ack_notify(pid, {:custom, :oops}) == :ok assert_receive {:terminate, {:error, {:bad_return_value, :oops}}} GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.ack_notify(pid, :raise) == :ok assert_receive {:terminate, {:error, {%RuntimeError{}, _}}} after Logger.add_backend(:console, flush: true) end test "sync_notify/2" do {:ok, pid} = GenEvent.start() GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.sync_notify(pid, :hello) == :ok assert_received {:event, :hello} assert GenEvent.sync_notify(pid, {:custom, :remove_handler}) == :ok assert_received {:terminate, :remove_handler} assert GenEvent.which_handlers(pid) == [] Logger.remove_backend(:console) GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.sync_notify(pid, {:custom, :oops}) == :ok assert_received {:terminate, {:error, {:bad_return_value, :oops}}} GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.sync_notify(pid, :raise) == :ok assert_received {:terminate, {:error, {%RuntimeError{}, _}}} after Logger.add_backend(:console, flush: true) end test "call/3" do {:ok, pid} = GenEvent.start() GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert GenEvent.call(pid, ReplyHandler, :hello) == :ok assert_receive {:call, :hello} assert GenEvent.call(pid, ReplyHandler, {:custom, {:remove_handler, :ok}}) == :ok assert_receive {:terminate, :remove_handler} assert GenEvent.which_handlers(pid) == [] Logger.remove_backend(:console) GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert {:error, {:bad_return_value, :oops}} = GenEvent.call(pid, ReplyHandler, {:custom, :oops}) assert_receive {:terminate, {:error, {:bad_return_value, :oops}}} assert GenEvent.which_handlers(pid) == [] GenEvent.add_handler(pid, ReplyHandler, {self(), false}) assert {:error, {%RuntimeError{}, _}} = GenEvent.call(pid, ReplyHandler, :raise) assert_receive {:terminate, {:error, {%RuntimeError{}, _}}} assert GenEvent.which_handlers(pid) == [] after Logger.add_backend(:console, flush: true) end test "call/2 with bad args" do Logger.remove_backend(:console) {:ok, pid} = GenEvent.start_link() assert GenEvent.add_handler(pid, DefaultHandler, []) == :ok assert GenEvent.call(pid, UnknownHandler, :messages) == {:error, :not_found} assert GenEvent.call(pid, DefaultHandler, :whatever) == {:error, {:bad_call, :whatever}} assert GenEvent.which_handlers(pid) == [] assert GenEvent.stop(pid) == :ok after Logger.add_backend(:console, flush: true) end test "add_process_handler/2 with GenEvent" do {:ok, snd} = GenEvent.start_link() GenEvent.add_handler(snd, ReplyHandler, {self(), false}) {:ok, fst} = GenEvent.start_link() :gen.call(fst, self(), {:add_process_handler, snd, snd}) assert GenEvent.notify(fst, :hello) == :ok assert_receive {:event, :hello} assert GenEvent.ack_notify(fst, :hello) == :ok assert_receive {:event, :hello} assert GenEvent.sync_notify(fst, :hello) == :ok assert_received {:event, :hello} end test ":sys.get_status/2" do {:ok, pid} = GenEvent.start() :ok = GenEvent.add_handler(pid, {ReplyHandler, :ok}, {self(), true}) self = self() status = :sys.get_status(pid) GenEvent.stop(pid) assert {:status, ^pid, {:module, GenEvent}, [pdict, _, ^pid, [], data]} = status assert pdict[:"$ancestors"] == [self()] assert pdict[:"$initial_call"] == {GenEvent, :init_it, 6} assert {'Installed handlers', [ {:handler, ReplyHandler, {ReplyHandler, :ok}, ^self, nil, nil}]} = data[:items] end test ":sys.get_state/1 and :sys.replace_state/2" do {:ok, pid} = GenEvent.start_link() self = self() assert [] = :sys.get_state(pid) :ok = GenEvent.add_handler(pid, ReplyHandler, {self, true}) assert [{ReplyHandler, ReplyHandler, ^self}] = :sys.get_state(pid) replacer = fn {ReplyHandler, ReplyHandler, _} -> {ReplyHandler, ReplyHandler, :unknown} end :sys.replace_state(pid, replacer) assert [{ReplyHandler, ReplyHandler, :unknown}] = :sys.get_state(pid) # Fail while replacing does not cause a crash :sys.replace_state(pid, fn _ -> exit(:fail) end) assert [{ReplyHandler, ReplyHandler, :unknown}] = :sys.get_state(pid) :ok = GenEvent.add_handler(pid, {ReplyHandler, :ok}, {self, true}) assert [{ReplyHandler, {ReplyHandler, :ok}, ^self}, {ReplyHandler, ReplyHandler, :unknown}] = :sys.get_state(pid) :ok = :sys.suspend(pid) assert [{ReplyHandler, {ReplyHandler, :ok}, ^self}, {ReplyHandler, ReplyHandler, :unknown}] = :sys.get_state(pid) :ok = :sys.resume(pid) end defp hibernating?(pid) do Process.info(pid, :current_function) == {:current_function, {:erlang, :hibernate, 3}} end defp wait_until(fun, counter \\ 0) do cond do counter > 100 -> flunk "Waited for 1s, but #{inspect fun} never returned true" fun.() -> true true -> receive after: (10 -> wait_until(fun, counter + 1)) end end defp wake_up(pid) do send pid, :wake assert_receive {:info, :wake} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/gen_server_test.exs000066400000000000000000000047661254730255300253660ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule GenServerTest do use ExUnit.Case, async: true defmodule Stack do use GenServer def handle_call(:stop, from, state) do GenServer.reply(from, :ok) {:stop, :normal, state} end def handle_call(:pop, _from, [h|t]) do {:reply, h, t} end def handle_call(request, from, state) do super(request, from, state) end def handle_cast({:push, item}, state) do {:noreply, [item|state]} end def handle_cast(request, state) do super(request, state) end def terminate(_reason, _state) do # There is a race condition if the agent is # restarted too fast and it is registered. try do self |> Process.info(:registered_name) |> elem(1) |> Process.unregister rescue _ -> :ok end :ok end end test "start_link/2, call/2 and cast/2" do {:ok, pid} = GenServer.start_link(Stack, [:hello]) {:links, links} = Process.info(self, :links) assert pid in links assert GenServer.call(pid, :pop) == :hello assert GenServer.cast(pid, {:push, :world}) == :ok assert GenServer.call(pid, :pop) == :world assert GenServer.call(pid, :stop) == :ok assert GenServer.cast({:global, :foo}, {:push, :world}) == :ok assert GenServer.cast({:via, :foo, :bar}, {:push, :world}) == :ok assert_raise ArgumentError, fn -> GenServer.cast(:foo, {:push, :world}) end end test "nil name" do {:ok, pid} = GenServer.start_link(Stack, [:hello], name: nil) assert Process.info(pid, :registered_name) == {:registered_name, []} end test "start/2" do {:ok, pid} = GenServer.start(Stack, [:hello]) {:links, links} = Process.info(self, :links) refute pid in links GenServer.call(pid, :stop) end test "abcast/3" do {:ok, _} = GenServer.start_link(Stack, [], name: :stack) assert GenServer.abcast(:stack, {:push, :hello}) == :abcast assert GenServer.call({:stack, node()}, :pop) == :hello assert GenServer.abcast([node, :foo@bar], :stack, {:push, :world}) == :abcast assert GenServer.call(:stack, :pop) == :world GenServer.call(:stack, :stop) end test "multi_call/4" do {:ok, _} = GenServer.start_link(Stack, [:hello, :world], name: :stack) assert GenServer.multi_call(:stack, :pop) == {[{node(), :hello}], []} assert GenServer.multi_call([node, :foo@bar], :stack, :pop) == {[{node, :world}], [:foo@bar]} GenServer.call(:stack, :stop) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/hash_dict_test.exs000066400000000000000000000043671254730255300251520ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule HashDictTest do use ExUnit.Case, async: true @dict Enum.into([foo: :bar], HashDict.new) test "access" do dict = Enum.into([foo: :baz], HashDict.new) assert Access.get(@dict, :foo) == :bar assert Access.get_and_update(@dict, :foo, fn :bar -> {:ok, :baz} end) == {:ok, dict} assert Access.get_and_update(HashDict.new, :foo, fn nil -> {:ok, :baz} end) == {:ok, dict} end test "is serializable as attribute" do assert @dict == Enum.into([foo: :bar], HashDict.new) end test "is accessible as attribute" do assert @dict[:foo] == :bar end test "small dict smoke test" do smoke_test(1..8) smoke_test(8..1) end test "medium dict smoke test" do smoke_test(1..80) smoke_test(80..1) end test "large dict smoke test" do smoke_test(1..1200) smoke_test(1200..1) end test "reduce/3 (via to_list)" do dict = filled_dict(8) list = dict |> HashDict.to_list assert length(list) == 8 assert {1, 1} in list assert list == Enum.to_list(dict) dict = filled_dict(20) list = dict |> HashDict.to_list assert length(list) == 20 assert {1, 1} in list assert list == Enum.to_list(dict) dict = filled_dict(120) list = dict |> HashDict.to_list assert length(list) == 120 assert {1, 1} in list assert list == Enum.to_list(dict) end test "comparison when subsets" do d1 = Enum.into [a: 0], HashDict.new d2 = Enum.into [a: 0, b: 1], HashDict.new refute HashDict.equal?(d1, d2) refute HashDict.equal?(d2, d1) end defp smoke_test(range) do {dict, _} = Enum.reduce range, {HashDict.new, 1}, fn(x, {acc, i}) -> acc = HashDict.put(acc, x, x) assert HashDict.size(acc) == i {acc, i + 1} end Enum.each range, fn(x) -> assert HashDict.get(dict, x) == x end {dict, _} = Enum.reduce range, {dict, Enum.count(range)}, fn(x, {acc, i}) -> assert HashDict.size(acc) == i acc = HashDict.delete(acc, x) assert HashDict.size(acc) == i - 1 assert HashDict.get(acc, x) == nil {acc, i - 1} end assert dict == HashDict.new end defp filled_dict(range) do Enum.reduce 1..range, HashDict.new, &HashDict.put(&2, &1, &1) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/hash_set_test.exs000066400000000000000000000043611254730255300250140ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule HashSetTest do use ExUnit.Case, async: true alias HashSet, as: S test "put" do assert S.equal?(S.put(S.new, 1), make([1])) assert S.equal?(S.put(make([1, 3, 4]), 2), make(1..4)) assert S.equal?(S.put(make(5..100), 10), make(5..100)) end test "union" do assert S.equal?(S.union(make([1, 3, 4]), S.new), make([1, 3, 4])) assert S.equal?(S.union(make(5..15), make(10..25)), make(5..25)) assert S.equal?(S.union(make(1..120), make(1..100)), make(1..120)) end test "intersection" do assert S.equal?(S.intersection(S.new, make(1..21)), S.new) assert S.equal?(S.intersection(make(1..21), make(4..24)), make(4..21)) assert S.equal?(S.intersection(make(2..100), make(1..120)), make(2..100)) end test "difference" do assert S.equal?(S.difference(make(2..20), S.new), make(2..20)) assert S.equal?(S.difference(make(2..20), make(1..21)), S.new) assert S.equal?(S.difference(make(1..101), make(2..100)), make([1, 101])) end test "disjoint?" do assert S.disjoint?(S.new, S.new) assert S.disjoint?(make(1..6), make(8..20)) refute S.disjoint?(make(1..6), make(5..15)) refute S.disjoint?(make(1..120), make(1..6)) end test "subset?" do assert S.subset?(S.new, S.new) assert S.subset?(make(1..6), make(1..10)) assert S.subset?(make(1..6), make(1..120)) refute S.subset?(make(1..120), make(1..6)) end test "equal?" do assert S.equal?(S.new, S.new) refute S.equal?(make(1..20), make(2..21)) assert S.equal?(make(1..120), make(1..120)) end test "delete" do assert S.equal?(S.delete(S.new, 1), S.new) assert S.equal?(S.delete(make(1..4), 5), make(1..4)) assert S.equal?(S.delete(make(1..4), 1), make(2..4)) assert S.equal?(S.delete(make(1..4), 2), make([1, 3, 4])) end test "size" do assert S.size(S.new) == 0 assert S.size(make(5..15)) == 11 assert S.size(make(2..100)) == 99 end test "to_list" do assert S.to_list(S.new) == [] list = S.to_list(make(1..20)) assert Enum.sort(list) == Enum.to_list(1..20) list = S.to_list(make(5..120)) assert Enum.sort(list) == Enum.to_list(5..120) end defp make(collection) do Enum.into(collection, S.new) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/inspect/000077500000000000000000000000001254730255300230775ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/inspect/algebra_test.exs000066400000000000000000000077031254730255300262630ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Inspect.AlgebraTest do use ExUnit.Case, async: true import Inspect.Algebra def helloabcd do concat( glue( glue( glue("hello", "a"), "b"), "c"), "d") end def sdoc(doc) do format(group(doc), :infinity) end defp render(doc, limit) do format(doc, limit) |> IO.iodata_to_binary end test "empty doc" do # Consistence with definitions assert empty == :doc_nil # Consistence of corresponding sdoc assert sdoc(empty) == [] # Consistent formatting assert render(empty, 80) == "" end test "break doc" do # Consistence with definitions assert break("break") == {:doc_break, "break"} assert break("") == {:doc_break, ""} # Wrong argument type assert_raise FunctionClauseError, fn -> break(42) end # Consistence of corresponding sdoc assert sdoc(break("_")) == ["_"] # Consistent formatting assert render(break("_"), 80) == "_" end test "glue doc" do # Consistence with definitions assert glue("a", "->", "b") == {:doc_cons, "a", {:doc_cons, {:doc_break, "->"}, "b"} } assert glue("a", "b") == glue("a", " ", "b") # Wrong argument type assert_raise FunctionClauseError, fn -> glue("a", 42, "b") end end test "text doc" do # Consistence of corresponding sdoc assert sdoc("_") == ["_"] # Consistent formatting assert render("_", 80) == "_" end test "space doc" do # Consistency with definitions assert space("a", "b") == {:doc_cons, "a", {:doc_cons, " ", "b"} } end test "nest doc" do # Consistence with definitions assert nest(empty, 1) == {:doc_nest, empty, 1} assert nest(empty, 0) == :doc_nil # Wrong argument type assert_raise FunctionClauseError, fn -> nest("foo", empty) end # Consistence of corresponding sdoc assert sdoc(nest("a", 1)) == ["a"] # Consistent formatting assert render(nest("a", 1), 80) == "a" assert render(nest(glue("a", "b"), 1), 2) == "a\n b" end test "line doc" do # Consistency with definitions assert line("a", "b") == {:doc_cons, "a", {:doc_cons, :doc_line, "b"}} # Consistence of corresponding sdoc assert sdoc(line("a", "b")) == ["a", "\n", "b"] # Consistent formatting assert render(line(glue("aaa", "bbb"), glue("ccc", "ddd")), 10) == "aaa bbb\nccc ddd" end test "group doc" do # Consistency with definitions assert group(glue("a", "b")) == {:doc_group, {:doc_cons, "a", concat(break, "b")}} assert group(empty) == {:doc_group, empty} # Consistence of corresponding sdoc assert sdoc(glue("a", "b")) == ["a", " ", "b"] # Consistent formatting assert render(helloabcd, 5) == "hello\na b\ncd" assert render(helloabcd, 80) == "hello a b cd" end test "formatting with infinity" do s = String.duplicate "x", 50 g = ";" doc = group(glue(s, g, s) |> glue(g, s) |> glue(g, s) |> glue(g, s)) assert render(doc, :infinity) == s <> g <> s <> g <> s <> g <> s <> g <> s end test "formatting surround_many with empty" do sm = &surround_many("[", &1, "]", %Inspect.Opts{}, fn(d, _) -> d end, ",") assert sm.([]) |> render(80) == "[]" assert sm.([empty]) |> render(80) == "[]" assert sm.([empty, empty]) |> render(80) == "[]" assert sm.(["a"]) |> render(80) == "[a]" assert sm.(["a", empty]) |> render(80) == "[a]" assert sm.([empty, "a"]) |> render(80) == "[a]" assert sm.(["a", empty, "b"]) |> render(80) == "[a, b]" assert sm.([empty, "a", "b"]) |> render(80) == "[a, b]" assert sm.(["a", "b", empty]) |> render(80) == "[a, b]" assert sm.(["a", "b" | "c"]) |> render(80) == "[a, b | c]" assert sm.(["a" | "b"]) |> render(80) == "[a | b]" assert sm.(["a" | empty]) |> render(80) == "[a]" assert sm.([empty | "b"]) |> render(80) == "[b]" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/inspect_test.exs000066400000000000000000000237641254730255300246730ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule Inspect.AtomTest do use ExUnit.Case, async: true test :basic do assert inspect(:foo) == ":foo" end test :empty do assert inspect(:"") == ":\"\"" end test :true_false_nil do assert inspect(false) == "false" assert inspect(true) == "true" assert inspect(nil) == "nil" end test :with_uppercase do assert inspect(:fOO) == ":fOO" assert inspect(:FOO) == ":FOO" end test :alias_atom do assert inspect(Foo) == "Foo" assert inspect(Foo.Bar) == "Foo.Bar" assert inspect(Elixir) == "Elixir" assert inspect(Elixir.Elixir) == "Elixir.Elixir" end test :with_integers do assert inspect(User1) == "User1" assert inspect(:user1) == ":user1" end test :with_punctuation do assert inspect(:foo?) == ":foo?" assert inspect(:bar!) == ":bar!" end test :op do assert inspect(:+) == ":+" assert inspect(:<~) == ":<~" assert inspect(:~>) == ":~>" assert inspect(:&&&) == ":&&&" assert inspect(:~~~) == ":~~~" assert inspect(:<<~) == ":<<~" assert inspect(:~>>) == ":~>>" assert inspect(:<~>) == ":<~>" assert inspect(:<|>) == ":<|>" end test :... do assert inspect(:...) == ":..." end test :@ do assert inspect(:@) == ":@" assert inspect(:foo@bar) == ":foo@bar" assert inspect(:foo@bar@) == ":foo@bar@" assert inspect(:foo@bar@baz) == ":foo@bar@baz" end test :others do assert inspect(:<<>>) == ":<<>>" assert inspect(:{}) == ":{}" assert inspect(:%{}) == ":%{}" assert inspect(:%) == ":%" end end defmodule Inspect.BitStringTest do use ExUnit.Case, async: true test :bitstring do assert inspect(<<1 :: size(12)-integer-signed>>) == "<<0, 1::size(4)>>" end test :binary do assert inspect("foo") == "\"foo\"" assert inspect(<>) == "\"abc\"" end test :escape do assert inspect("f\no") == "\"f\\no\"" assert inspect("f\\o") == "\"f\\\\o\"" assert inspect("f\ao") == "\"f\\ao\"" end test :utf8 do assert inspect(" ゆんゆん") == "\" ゆんゆん\"" end test :all_escapes do assert inspect("\a\b\d\e\f\n\r\s\t\v") == "\"\\a\\b\\d\\e\\f\\n\\r \\t\\v\"" end test :opt_infer do assert inspect(<<"john", 193, "doe">>, binaries: :infer) == ~s(<<106, 111, 104, 110, 193, 100, 111, 101>>) assert inspect(<<"john">>, binaries: :infer) == ~s("john") assert inspect(<<193>>, binaries: :infer) == ~s(<<193>>) end test :opt_as_strings do assert inspect(<<"john", 193, "doe">>, binaries: :as_strings) == ~s("john\\xC1doe") assert inspect(<<"john">>, binaries: :as_strings) == ~s("john") assert inspect(<<193>>, binaries: :as_strings) == ~s("\\xC1") end test :opt_as_binaries do assert inspect(<<"john", 193, "doe">>, binaries: :as_binaries) == "<<106, 111, 104, 110, 193, 100, 111, 101>>" assert inspect(<<"john">>, binaries: :as_binaries) == "<<106, 111, 104, 110>>" assert inspect(<<193>>, binaries: :as_binaries) == "<<193>>" end test :unprintable_with_opts do assert inspect(<<193, 193, 193, 193>>, limit: 3) == "<<193, 193, 193, ...>>" end end defmodule Inspect.NumberTest do use ExUnit.Case, async: true test :integer do assert inspect(100) == "100" end test :decimal do assert inspect(100, base: :decimal) == "100" end test :hex do assert inspect(100, base: :hex) == "0x64" end test :octal do assert inspect(100, base: :octal) == "0o144" end test :binary do assert inspect(86, base: :binary) == "0b1010110" end test :float do assert inspect(1.0) == "1.0" assert inspect(1.0E10) == "1.0e10" assert inspect(1.0e10) == "1.0e10" assert inspect(1.0e-10) == "1.0e-10" end end defmodule Inspect.TupleTest do use ExUnit.Case test :basic do assert inspect({1, "b", 3}) == "{1, \"b\", 3}" assert inspect({1, "b", 3}, [pretty: true, width: 1]) == "{1,\n \"b\",\n 3}" end test :empty do assert inspect({}) == "{}" end test :with_limit do assert inspect({1, 2, 3, 4}, limit: 3) == "{1, 2, 3, ...}" end end defmodule Inspect.ListTest do use ExUnit.Case, async: true test :basic do assert inspect([ 1, "b", 3 ]) == "[1, \"b\", 3]" assert inspect([ 1, "b", 3 ], [pretty: true, width: 1]) == "[1,\n \"b\",\n 3]" end test :printable do assert inspect('abc') == "'abc'" end test :keyword do assert inspect([a: 1]) == "[a: 1]" assert inspect([a: 1, b: 2]) == "[a: 1, b: 2]" assert inspect([a: 1, a: 2, b: 2]) == "[a: 1, a: 2, b: 2]" assert inspect(["123": 1]) == ~s(["123": 1]) assert inspect([foo: [1, 2, 3, :bar], bazzz: :bat], [pretty: true, width: 30]) == "[foo: [1, 2, 3, :bar],\n bazzz: :bat]" end test :opt_infer do assert inspect('john' ++ [0] ++ 'doe', char_lists: :infer) == "[106, 111, 104, 110, 0, 100, 111, 101]" assert inspect('john', char_lists: :infer) == "'john'" assert inspect([0], char_lists: :infer) == "[0]" end test :opt_as_strings do assert inspect('john' ++ [0] ++ 'doe', char_lists: :as_char_lists) == "'john\\0doe'" assert inspect('john', char_lists: :as_char_lists) == "'john'" assert inspect([0], char_lists: :as_char_lists) == "'\\0'" end test :opt_as_lists do assert inspect('john' ++ [0] ++ 'doe', char_lists: :as_lists) == "[106, 111, 104, 110, 0, 100, 111, 101]" assert inspect('john', char_lists: :as_lists) == "[106, 111, 104, 110]" assert inspect([0], char_lists: :as_lists) == "[0]" end test :non_printable do assert inspect([{:b, 1}, {:a, 1}]) == "[b: 1, a: 1]" end test :improper do assert inspect([:foo | :bar]) == "[:foo | :bar]" assert inspect([1, 2, 3, 4, 5|42], [pretty: true, width: 1]) == "[1,\n 2,\n 3,\n 4,\n 5 |\n 42]" end test :nested do assert inspect(Enum.reduce(1..100, [0], &[&2, Integer.to_string(&1)]), [limit: 5]) == "[[[[[[...], ...], \"97\"], \"98\"], \"99\"], \"100\"]" assert inspect(Enum.reduce(1..100, [0], &[&2 | Integer.to_string(&1)]), [limit: 5]) == "[[[[[[...] | \"96\"] | \"97\"] | \"98\"] | \"99\"] | \"100\"]" end test :codepoints do assert inspect('é') == "[233]" end test :empty do assert inspect([]) == "[]" end test :with_limit do assert inspect([ 1, 2, 3, 4 ], limit: 3) == "[1, 2, 3, ...]" end end defmodule Inspect.MapTest do use ExUnit.Case test :basic do assert inspect(%{1 => "b"}) == "%{1 => \"b\"}" assert inspect(%{1 => "b", 2 => "c"}, [pretty: true, width: 1]) == "%{1 => \"b\",\n 2 => \"c\"}" end test :keyword do assert inspect(%{a: 1}) == "%{a: 1}" assert inspect(%{a: 1, b: 2}) == "%{a: 1, b: 2}" assert inspect(%{a: 1, b: 2, c: 3}) == "%{a: 1, b: 2, c: 3}" end test :with_limit do assert inspect(%{1 => 1, 2 => 2, 3 => 3, 4 => 4}, limit: 3) == "%{1 => 1, 2 => 2, 3 => 3, ...}" end defmodule Public do def __struct__ do %{key: 0, __struct__: Public} end end defmodule Private do end test :public_struct do assert inspect(%Public{key: 1}) == "%Inspect.MapTest.Public{key: 1}" end test :public_modified_struct do public = %Public{key: 1} assert inspect(Map.put(public, :foo, :bar)) == "%{__struct__: Inspect.MapTest.Public, foo: :bar, key: 1}" end test :private_struct do assert inspect(%{__struct__: Private, key: 1}) == "%{__struct__: Inspect.MapTest.Private, key: 1}" end defmodule Failing do def __struct__ do %{key: 0} end defimpl Inspect do def inspect(struct, _) do struct.unknown end end end test :bad_implementation_unsafe do msg = "got KeyError with message `key :unknown not found in: " <> "%{__struct__: Inspect.MapTest.Failing, key: 0}` while " <> "inspecting %{__struct__: Inspect.MapTest.Failing, key: 0}" assert_raise Inspect.Error, msg, fn -> inspect(%Failing{}, safe: false) end assert [{Inspect.Inspect.MapTest.Failing, :inspect, 2, _}|_] = System.stacktrace end test :bad_implementation_safe do msg = "got KeyError with message `key :unknown not found in: " <> "%{__struct__: Inspect.MapTest.Failing, key: 0}` while " <> "inspecting %{__struct__: Inspect.MapTest.Failing, key: 0}" assert inspect(%Failing{}) == "%Inspect.Error{message: \"#{msg}\"}" end test :exception do assert inspect(%RuntimeError{message: "runtime error"}) == "%RuntimeError{message: \"runtime error\"}" end end defmodule Inspect.OthersTest do use ExUnit.Case, async: true def f do fn() -> :ok end end test :external_elixir_funs do bin = inspect(&Enum.map/2) assert bin == "&Enum.map/2" end test :external_erlang_funs do bin = inspect(&:lists.map/2) assert bin == "&:lists.map/2" end test :outdated_functions do defmodule V do def fun do fn -> 1 end end end Application.put_env(:elixir, :anony, V.fun) Application.put_env(:elixir, :named, &V.fun/0) :code.delete(V) :code.purge(V) anony = Application.get_env(:elixir, :anony) named = Application.get_env(:elixir, :named) assert inspect(anony) =~ ~r"#Function<0.\d+/0 in Inspect.OthersTest.V>" assert inspect(named) =~ ~r"&Inspect.OthersTest.V.fun/0" after Application.delete_env(:elixir, :anony) Application.delete_env(:elixir, :named) end test :other_funs do assert "#Function<" <> _ = inspect(fn(x) -> x + 1 end) assert "#Function<" <> _ = inspect(f) end test :hash_dict_set do assert "#HashDict<" <> _ = inspect(HashDict.new) assert "#HashSet<" <> _ = inspect(HashSet.new) end test :map_set do assert "#MapSet<" <> _ = inspect(MapSet.new) end test :pids do assert "#PID<" <> _ = inspect(self) end test :references do assert "#Reference<" <> _ = inspect(make_ref) end test :regex do "~r/foo/m" = inspect(~r(foo)m) "~r/\\a\\x08\\x7F\\x1B\\f\\n\\r \\t\\v\\//" = inspect(Regex.compile!("\a\b\d\e\f\n\r\s\t\v/")) "~r/\\a\\b\\d\\e\\f\\n\\r\\s\\t\\v\\//" = inspect(~r<\a\b\d\e\f\n\r\s\t\v/>) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/integer_test.exs000066400000000000000000000051651254730255300246560ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule IntegerTest do use ExUnit.Case, async: true require Integer test :odd? do assert Integer.is_odd(0) == false assert Integer.is_odd(1) == true assert Integer.is_odd(2) == false assert Integer.is_odd(3) == true assert Integer.is_odd(-1) == true assert Integer.is_odd(-2) == false assert Integer.is_odd(-3) == true end test :even? do assert Integer.is_even(0) == true assert Integer.is_even(1) == false assert Integer.is_even(2) == true assert Integer.is_even(3) == false assert Integer.is_even(-1) == false assert Integer.is_even(-2) == true assert Integer.is_even(-3) == false end test :digits do assert Integer.digits(101) == [1, 0, 1] assert Integer.digits(1) == [1] assert Integer.digits(0) == [0] assert Integer.digits(0, 2) == [0] assert Integer.digits(58127, 2) == [1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1] end test :undigits do assert Integer.undigits([1, 0, 1]) == 101 assert Integer.undigits([1]) == 1 assert Integer.undigits([0]) == 0 assert Integer.undigits([]) == 0 assert Integer.undigits([1, 4], 16) == 0x14 assert Integer.undigits([1, 4], 8) == 0o14 assert Integer.undigits([1, 1], 2) == 0b11 assert Integer.undigits([1, 2, 3, 4, 5]) == 12345 assert Integer.undigits([1, 0, -5]) == 95 assert Integer.undigits([-1, -1, -5]) == -115 end test :parse do assert Integer.parse("12") === {12, ""} assert Integer.parse("-12") === {-12, ""} assert Integer.parse("123456789") === {123456789, ""} assert Integer.parse("12.5") === {12, ".5"} assert Integer.parse("7.5e-3") === {7, ".5e-3"} assert Integer.parse("12x") === {12, "x"} assert Integer.parse("++1") === :error assert Integer.parse("--1") === :error assert Integer.parse("+-1") === :error assert Integer.parse("three") === :error assert Integer.parse("12", 10) === {12, ""} assert Integer.parse("-12", 12) === {-14, ""} assert Integer.parse("12345678", 9) === {6053444, ""} assert Integer.parse("3.14", 4) === {3, ".14"} assert Integer.parse("64eb", 16) === {25835, ""} assert Integer.parse("64eb", 10) === {64, "eb"} assert Integer.parse("10", 2) === {2, ""} assert Integer.parse("++4", 10) === :error # Base should be in range 2..36 assert_raise ArgumentError, "invalid base 0", fn -> Integer.parse("2", 0) end assert_raise ArgumentError, "invalid base 41", fn -> Integer.parse("2", 41) end # Base should be an integer assert_raise ArgumentError, "invalid base 10.2", fn -> Integer.parse("2", 10.2) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/io/000077500000000000000000000000001254730255300220415ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/io/ansi/000077500000000000000000000000001254730255300227735ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/io/ansi/docs_test.exs000066400000000000000000000236741254730255300255170ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule IO.ANSI.DocsTest do use ExUnit.Case, async: true import ExUnit.CaptureIO def format_heading(str) do capture_io(fn -> IO.ANSI.Docs.print_heading(str, []) end) |> String.rstrip end def format(str) do capture_io(fn -> IO.ANSI.Docs.print(str, []) end) |> String.rstrip end test "heading is formatted" do result = format_heading("wibble") assert String.starts_with?(result, "\e[0m\n\e[7m\e[33m") assert String.ends_with?(result, "\e[0m\n\e[0m") assert String.contains?(result, " wibble ") end test "first level heading is converted" do result = format("# wibble\n\ntext\n") assert result == "\e[33mWIBBLE\e[0m\n\e[0m\ntext\n\e[0m" end test "second level heading is converted" do result = format("## wibble\n\ntext\n") assert result == "\e[33mwibble\e[0m\n\e[0m\ntext\n\e[0m" end test "third level heading is converted" do result = format("## wibble\n\ntext\n") assert result == "\e[33mwibble\e[0m\n\e[0m\ntext\n\e[0m" end test "code block is converted" do result = format("line\n\n code\n code2\n\nline2\n") assert result == "line\n\e[0m\n\e[36m\e[1m┃ code\n┃ code2\e[0m\n\e[0m\nline2\n\e[0m" end test "fenced code block is converted" do result = format("line\n```\ncode\ncode2\n```\nline2\n") assert result == "line\n\e[0m\n\e[36m\e[1m┃ code\n┃ code2\e[0m\n\e[0m\nline2\n\e[0m" result = format("line\n```elixir\ncode\ncode2\n```\nline2\n") assert result == "line\n\e[0m\n\e[36m\e[1m┃ code\n┃ code2\e[0m\n\e[0m\nline2\n\e[0m" result = format("line\n~~~elixir\ncode\n```\n~~~\nline2\n") assert result == "line\n\e[0m\n\e[36m\e[1m┃ code\n┃ ```\e[0m\n\e[0m\nline2\n\e[0m" end test "* list is converted" do result = format("* one\n* two\n* three\n") assert result == " • one\n • two\n • three\n\e[0m" end test "* list surrounded by text is converted" do result = format("Count:\n\n* one\n* two\n* three\n\nDone") assert result == "Count:\n\e[0m\n • one\n • two\n • three\n\e[0m\nDone\n\e[0m" end test "* list with continuation is converted" do result = format("* one\ntwo\n\n three\nfour\n* five") assert result == " • one two\n three four\n\e[0m\n • five\n\e[0m" end test "* nested lists are converted" do result = format("* one\n * one.one\n * one.two\n* two") assert result == " • one\n • one.one\n • one.two\n\e[0m\n • two\n\e[0m" end test "* lists with spaces are converted" do result = format(" * one\n * two\n * three") assert result == " • one\n • two\n • three\n\e[0m" end test "* lists with code" do result = format(" * one\n two three") assert result == " • one\n\e[36m\e[1m ┃ two three\e[0m\n\e[0m\n\e[0m" end test "- list is converted" do result = format("- one\n- two\n- three\n") assert result == " • one\n • two\n • three\n\e[0m" end test "+ list is converted" do result = format("+ one\n+ two\n+ three\n") assert result == " • one\n • two\n • three\n\e[0m" end test "+ and - nested lists are converted" do result = format("- one\n + one.one\n + one.two\n- two") assert result == " • one\n • one.one\n • one.two\n\e[0m\n • two\n\e[0m" end test "paragraphs are split" do result = format("para1\n\npara2") assert result == "para1\n\e[0m\npara2\n\e[0m" end test "extra whitespace is ignored between paras" do result = format("para1\n \npara2") assert result == "para1\n\e[0m\npara2\n\e[0m" end test "extra whitespace doesn't mess up a following list" do result = format("para1\n \n* one\n* two") assert result == "para1\n\e[0m\n • one\n • two\n\e[0m" end test "star/underscore/backtick works" do result = format("*world*") assert result == "\e[1mworld\e[0m\n\e[0m" result = format("*world*.") assert result == "\e[1mworld\e[0m.\n\e[0m" result = format("**world**") assert result == "\e[1mworld\e[0m\n\e[0m" result = format("_world_") assert result == "\e[4mworld\e[0m\n\e[0m" result = format("`world`") assert result == "\e[36mworld\e[0m\n\e[0m" end test "star/underscore/backtick works across words" do result = format("*hello world*") assert result == "\e[1mhello world\e[0m\n\e[0m" result = format("**hello world**") assert result == "\e[1mhello world\e[0m\n\e[0m" result = format("_hello world_") assert result == "\e[4mhello world\e[0m\n\e[0m" result = format("`hello world`") assert result == "\e[36mhello world\e[0m\n\e[0m" end test "multiple stars/underscores/backticks work" do result = format("*hello world* *hello world*") assert result == "\e[1mhello world\e[0m \e[1mhello world\e[0m\n\e[0m" result = format("_hello world_ _hello world_") assert result == "\e[4mhello world\e[0m \e[4mhello world\e[0m\n\e[0m" result = format("`hello world` `hello world`") assert result == "\e[36mhello world\e[0m \e[36mhello world\e[0m\n\e[0m" end test "multiple stars/underscores/backticks work when separated by other words" do result = format("*hello world* unit test *hello world*") assert result == "\e[1mhello world\e[0m unit test \e[1mhello world\e[0m\n\e[0m" result = format("_hello world_ unit test _hello world_") assert result == "\e[4mhello world\e[0m unit test \e[4mhello world\e[0m\n\e[0m" result = format("`hello world` unit test `hello world`") assert result == "\e[36mhello world\e[0m unit test \e[36mhello world\e[0m\n\e[0m" end test "star/underscore preceeded by space doesn't get interpreted" do result = format("_unit _size") assert result == "_unit _size\n\e[0m" result = format("**unit **size") assert result == "**unit **size\n\e[0m" result = format("*unit *size") assert result == "*unit *size\n\e[0m" end test "star/underscore/backtick preceeded by non-space delimiters gets interpreted" do result = format("(`hello world`)") assert result == "(\e[36mhello world\e[0m)\n\e[0m" result = format("<`hello world`>") assert result == "<\e[36mhello world\e[0m>\n\e[0m" result = format("(*hello world*)") assert result == "(\e[1mhello world\e[0m)\n\e[0m" result = format("@*hello world*@") assert result == "@\e[1mhello world\e[0m@\n\e[0m" result = format("(_hello world_)") assert result == "(\e[4mhello world\e[0m)\n\e[0m" result = format("'_hello world_'") assert result == "'\e[4mhello world\e[0m'\n\e[0m" end test "star/underscore/backtick starts/ends within a word doesn't get interpreted" do result = format("foo_bar, foo_bar_baz!") assert result == "foo_bar, foo_bar_baz!\n\e[0m" result = format("_foo_bar") assert result == "_foo_bar\n\e[0m" result = format("foo_bar_") assert result == "foo_bar_\n\e[0m" result = format("foo*bar, foo*bar*baz!") assert result == "foo*bar, foo*bar*baz!\n\e[0m" result = format("*foo*bar") assert result == "*foo*bar\n\e[0m" result = format("foo*bar*") assert result == "foo*bar*\n\e[0m" end test "backtick preceeded by space gets interpreted" do result = format("`unit `size") assert result == "\e[36munit \e[0msize\n\e[0m" end test "star/underscore/backtick with leading escape" do result = format("\\_unit_") assert result == "_unit_\n\e[0m" result = format("\\*unit*") assert result == "*unit*\n\e[0m" result = format("\\`unit`") assert result == "`unit`\n\e[0m" end test "star/underscore/backtick with closing escape" do result = format("_unit\\_") assert result == "_unit_\n\e[0m" result = format("*unit\\*") assert result == "*unit*\n\e[0m" result = format("`unit\\`") assert result == "\e[36munit\\\e[0m\n\e[0m" end test "star/underscore/backtick with double escape" do result = format("\\\\*world*") assert result == "\\\e[1mworld\e[0m\n\e[0m" result = format("\\\\_world_") assert result == "\\\e[4mworld\e[0m\n\e[0m" result = format("\\\\`world`") assert result == "\\\e[36mworld\e[0m\n\e[0m" end test "star/underscore/backtick when incomplete" do result = format("unit_size") assert result == "unit_size\n\e[0m" result = format("unit`size") assert result == "unit`size\n\e[0m" result = format("unit*size") assert result == "unit*size\n\e[0m" result = format("unit**size") assert result == "unit**size\n\e[0m" end test "backtick with escape" do result = format("`\\`") assert result == "\e[36m\\\e[0m\n\e[0m" end test "backtick close to underscores gets interpreted as code" do result = format("`__world__`") assert result == "\e[36m__world__\e[0m\n\e[0m" end test "escaping of underlines within links" do result = format("(http://en.wikipedia.org/wiki/ANSI_escape_code)") assert result == "(http://en.wikipedia.org/wiki/ANSI_escape_code)\n\e[0m" result = format("[ANSI escape code](http://en.wikipedia.org/wiki/ANSI_escape_code)") assert result == "ANSI escape code (http://en.wikipedia.org/wiki/ANSI_escape_code)\n\e[0m" end test "lone thing that looks like a table line isn't" do assert format("one\n2 | 3\ntwo\n") == "one 2 | 3 two\n\e[0m" end test "lone table line at end of input isn't" do assert format("one\n2 | 3") == "one 2 | 3\n\e[0m" end test "two successive table lines are a table" do assert format("a | b\none | two\n") == "a | b \none | two\n\e[0m" # note spacing end test "table with heading" do assert format("column 1 | and 2\n-- | --\na | b\none | two\n") == "\e[7mcolumn 1 | and 2\e[0m\na | b \none | two \n\e[0m" end test "table with formatting in cells" do assert format("`a` | _b_\nc | d") == "\e[36ma\e[0m | \e[4mb\e[0m\nc | d\n\e[0m" end test "table with variable number of columns" do assert format("a | b | c\nd | e") == "a | b | c\nd | e | \n\e[0m" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/io/ansi_test.exs000066400000000000000000000060421254730255300245550ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IO.ANSITest do use ExUnit.Case, async: true test :format_ansicode do assert IO.chardata_to_string(IO.ANSI.format(:green, true)) == "#{IO.ANSI.green}#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format(:green, false)) == "" end test :format_binary do assert IO.chardata_to_string(IO.ANSI.format("Hello, world!", true)) == "Hello, world!" assert IO.chardata_to_string(IO.ANSI.format("A map: %{foo: :bar}", false)) == "A map: %{foo: :bar}" end test :format_empty_list do assert IO.chardata_to_string(IO.ANSI.format([], true)) == "" assert IO.chardata_to_string(IO.ANSI.format([], false)) == "" end test :format_ansicode_list do assert IO.chardata_to_string(IO.ANSI.format([:red, :bright], true)) == "#{IO.ANSI.red}#{IO.ANSI.bright}#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format([:red, :bright], false)) == "" end test :format_binary_list do assert IO.chardata_to_string(IO.ANSI.format(["Hello, ", "world!"], true)) == "Hello, world!" assert IO.chardata_to_string(IO.ANSI.format(["Hello, ", "world!"], false)) == "Hello, world!" end test :format_char_list do assert IO.chardata_to_string(IO.ANSI.format('Hello, world!', true)) == "Hello, world!" assert IO.chardata_to_string(IO.ANSI.format('Hello, world!', false)) == "Hello, world!" end test :format_mixed_list do data = ["Hello", ?,, 32, :red, "world!"] assert IO.chardata_to_string(IO.ANSI.format(data, true)) == "Hello, #{IO.ANSI.red}world!#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format(data, false)) == "Hello, world!" end test :format_nested_list do data = ["Hello, ", ["nested", 32, :red, "world!"]] assert IO.chardata_to_string(IO.ANSI.format(data, true)) == "Hello, nested #{IO.ANSI.red}world!#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format(data, false)) == "Hello, nested world!" end test :format_improper_list do data = ["Hello, ", :red, "world" | "!"] assert IO.chardata_to_string(IO.ANSI.format(data, true)) == "Hello, #{IO.ANSI.red}world!#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format(data, false)) == "Hello, world!" end test :format_nested_improper_list do data = [["Hello, " | :red], "world!" | :green] assert IO.chardata_to_string(IO.ANSI.format(data, true)) == "Hello, #{IO.ANSI.red}world!#{IO.ANSI.green}#{IO.ANSI.reset}" assert IO.chardata_to_string(IO.ANSI.format(data, false)) == "Hello, world!" end test :format_fragment do assert IO.chardata_to_string(IO.ANSI.format_fragment([:red, "Hello!"], true)) == "#{IO.ANSI.red}Hello!" end test :format_invalid_sequence do assert_raise ArgumentError, "invalid ANSI sequence specification: brigh", fn -> IO.ANSI.format([:brigh, "Hello!"], true) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/io_test.exs000066400000000000000000000111341254730255300236210ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule IOTest do use ExUnit.Case, async: true import ExUnit.CaptureIO test :read_with_count do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__), [:char_list]) assert 'FOO' == IO.read(file, 3) assert File.close(file) == :ok end test :read_with_utf8_and_binary do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) assert "Русский" == IO.read(file, 7) assert File.close(file) == :ok end test :binread do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__)) assert "Русский" == IO.binread(file, 14) assert File.close(file) == :ok end test :binread_all do {:ok, file} = File.open(Path.expand('fixtures/file.bin', __DIR__)) assert "LF\nCR\rCRLF\r\nLFCR\n\r" == IO.binread(file, :all) assert File.close(file) == :ok end test :getn do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__)) assert "F" == IO.getn(file, "") assert "O" == IO.getn(file, "") assert "O" == IO.getn(file, "") assert "\n" == IO.getn(file, "") assert :eof == IO.getn(file, "") assert File.close(file) == :ok end test :getn_with_count do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__), [:char_list]) assert 'FOO' == IO.getn(file, "", 3) assert File.close(file) == :ok end test :getn_with_utf8_and_binary do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) assert "Русский" == IO.getn(file, "", 7) assert File.close(file) == :ok end test :gets do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__), [:char_list]) assert 'FOO\n' == IO.gets(file, "") assert :eof == IO.gets(file, "") assert File.close(file) == :ok end test :gets_with_utf8_and_binary do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) assert "Русский\n" == IO.gets(file, "") assert "日\n" == IO.gets(file, "") assert File.close(file) == :ok end test :readall do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__)) assert "FOO\n" == IO.read(file, :all) assert "" == IO.read(file, :all) assert File.close(file) == :ok end test :readall_with_utf8_and_binary do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) assert "Русский\n日\n" == IO.read(file, :all) assert "" == IO.read(file, :all) assert File.close(file) == :ok end test :readline do {:ok, file} = File.open(Path.expand('fixtures/file.txt', __DIR__)) assert "FOO\n" == IO.read(file, :line) assert :eof == IO.read(file, :line) assert File.close(file) == :ok end test :readline_with_utf8_and_binary do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__), [:utf8]) assert "Русский\n" == IO.read(file, :line) assert "日\n" == IO.read(file, :line) assert File.close(file) == :ok end test :binreadall do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__)) assert "Русский\n日\n" == IO.binread(file, :all) assert "" == IO.binread(file, :all) assert File.close(file) == :ok end test :binreadline do {:ok, file} = File.open(Path.expand('fixtures/utf8.txt', __DIR__)) assert "Русский\n" == IO.binread(file, :line) assert "日\n" == IO.binread(file, :line) assert File.close(file) == :ok end test :puts_with_chardata do assert capture_io(fn -> IO.puts("hello") end) == "hello\n" assert capture_io(fn -> IO.puts('hello') end) == "hello\n" assert capture_io(fn -> IO.puts(:hello) end) == "hello\n" assert capture_io(fn -> IO.puts(13) end) == "13\n" end test :write_with_chardata do assert capture_io(fn -> IO.write("hello") end) == "hello" assert capture_io(fn -> IO.write('hello') end) == "hello" assert capture_io(fn -> IO.write(:hello) end) == "hello" assert capture_io(fn -> IO.write(13) end) == "13" end test :gets_with_chardata do assert capture_io("foo\n", fn -> IO.gets("hello") end) == "hello" assert capture_io("foo\n", fn -> IO.gets('hello') end) == "hello" assert capture_io("foo\n", fn -> IO.gets(:hello) end) == "hello" assert capture_io("foo\n", fn -> IO.gets(13) end) == "13" end test :getn_with_chardata do assert capture_io("foo\n", fn -> IO.getn("hello", 3) end) == "hello" assert capture_io("foo\n", fn -> IO.getn('hello', 3) end) == "hello" assert capture_io("foo\n", fn -> IO.getn(:hello, 3) end) == "hello" assert capture_io("foo\n", fn -> IO.getn(13, 3) end) == "13" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/000077500000000000000000000000001254730255300227125ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/alias_test.exs000066400000000000000000000047161254730255300255730ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ alias Kernel.AliasTest.Nested, as: Nested defmodule Nested do def value, do: 1 end defmodule Kernel.AliasTest do use ExUnit.Case, async: true test :alias_erlang do alias :lists, as: MyList assert MyList.flatten([1, [2], 3]) == [1, 2, 3] assert Elixir.MyList.Bar == :"Elixir.MyList.Bar" assert MyList.Bar == :"Elixir.lists.Bar" end test :double_alias do alias Kernel.AliasTest.Nested, as: Nested2 assert Nested.value == 1 assert Nested2.value == 1 end test :overwriten_alias do alias List, as: Nested assert Nested.flatten([[13]]) == [13] end test :lexical do if true do alias OMG, as: List, warn: false else alias ABC, as: List, warn: false end assert List.flatten([1, [2], 3]) == [1, 2, 3] end defmodule Elixir do def sample, do: 1 end test :nested_elixir_alias do assert Kernel.AliasTest.Elixir.sample == 1 end end defmodule Kernel.AliasNestingGenerator do defmacro create do quote do defmodule Parent do def a, do: :a end defmodule Parent.Child do def b, do: Parent.a end end end end defmodule Kernel.AliasNestingTest do use ExUnit.Case, async: true require Kernel.AliasNestingGenerator Kernel.AliasNestingGenerator.create test :aliases_nesting do assert Parent.a == :a assert Parent.Child.b == :a end defmodule Nested do def value, do: 2 end test :aliases_nesting_with_previous_alias do assert Nested.value == 2 end end # Test case extracted from using records with aliases # and @before_compile. We are basically testing that # macro aliases are not leaking from the macro. defmodule Macro.AliasTest.Definer do defmacro __using__(_options) do quote do @before_compile unquote(__MODULE__) end end defmacro __before_compile__(_env) do quote do defmodule First do defstruct foo: :bar end defmodule Second do defstruct baz: %First{} end end end end defmodule Macro.AliasTest.Aliaser do defmacro __using__(_options) do quote do alias Some.First end end end defmodule Macro.AliasTest.User do use ExUnit.Case, async: true use Macro.AliasTest.Definer use Macro.AliasTest.Aliaser test "has a struct defined from after compile" do assert is_map struct(Macro.AliasTest.User.First, []) assert is_map struct(Macro.AliasTest.User.Second, []).baz end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/binary_test.exs000066400000000000000000000103721254730255300257610ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.BinaryTest do use ExUnit.Case, async: true test :heredoc do assert 7 == __ENV__.line assert "foo\nbar\n" == """ foo bar """ assert 13 == __ENV__.line assert "foo\nbar \"\"\"\n" == """ foo bar """ """ end test :aligned_heredoc do assert "foo\nbar\n" == """ foo bar """ end test :heredoc_with_interpolation do assert "29\n" == """ #{__ENV__.line} """ assert "\n34\n" == """ #{__ENV__.line} """ end test :heredoc_in_call do assert "foo\nbar" == Kernel.<>(""" foo """, "bar") end test :utf8 do assert byte_size(" ゆんゆん") == 13 end test :utf8_char do assert ?ゆ == 12422 assert ?\ゆ == 12422 end test :string_concatenation_as_match do "foo" <> x = "foobar" assert x == "bar" <<"foo">> <> x = "foobar" assert x == "bar" <<"f", "oo">> <> x = "foobar" assert x == "bar" <> <> _ = "foobar" assert x == "foo" size = 3 <> <> _ = "foobar" assert x == "foo" <> <> _ = "foobar" assert x == "foo" assert_raise CompileError, fn -> Code.eval_string(~s{<> <> _ = "foobar"}) end assert_raise CompileError, fn -> Code.eval_string(~s{<> <> _ = "foobar"}) end end test :hex do assert "\xa" == "\n" assert "\xE9" == "é" assert "\xFF" == "ÿ" assert "\x{A}"== "\n" assert "\x{E9}"== "é" assert "\x{10F}" == <<196, 143>> assert "\x{10FF}" == <<225, 131, 191>> assert "\x{10FFF}" == <<240, 144, 191, 191>> assert "\x{10FFFF}" == <<244, 143, 191, 191>> end test :match do assert match?(<< ?a, _ :: binary >>, "ab") refute match?(<< ?a, _ :: binary >>, "cd") assert match?(<< _ :: utf8 >> <> _, "éf") end test :interpolation do res = "hello \\abc" assert "hello #{"\\abc"}" == res assert "hello #{"\\abc" <> ""}" == res end test :pattern_match do s = 16 assert <<_a, _b :: size(s)>> = "foo" end test :pattern_match_with_splice do assert << 1, <<2, 3, 4>>, 5 >> = <<1, 2, 3, 4, 5>> end test :partial_application do assert (&<< &1, 2 >>).(1) == << 1, 2 >> assert (&<< &1, &2 >>).(1, 2) == << 1, 2 >> assert (&<< &2, &1 >>).(2, 1) == << 1, 2 >> end test :literal do assert <<106, 111, 115, 195, 169>> == << "josé" :: binary >> assert <<106, 111, 115, 195, 169>> == << "josé" :: bits >> assert <<106, 111, 115, 195, 169>> == << "josé" :: bitstring >> assert <<106, 111, 115, 195, 169>> == << "josé" :: bytes >> assert <<106, 111, 115, 195, 169>> == << "josé" :: utf8 >> assert <<0, 106, 0, 111, 0, 115, 0, 233>> == << "josé" :: utf16 >> assert <<106, 0, 111, 0, 115, 0, 233, 0>> == << "josé" :: little-utf16 >> assert <<0, 0, 0, 106, 0, 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 233>> == << "josé" :: utf32 >> end test :literal_errors do assert_raise CompileError, fn -> Code.eval_string(~s[<< "foo" :: integer >>]) end assert_raise CompileError, fn -> Code.eval_string(~s[<< "foo" :: float >>]) end assert_raise CompileError, fn -> Code.eval_string(~s[<< 'foo' :: binary >>]) end assert_raise ArgumentError, fn -> Code.eval_string(~s[<<1::size(4)>> <> "foo"]) end end @binary "new " test :bitsyntax_with_expansion do assert <<@binary, "world">> == "new world" end test :bitsyntax_translation do refb = "sample" sec_data = "another" << byte_size(refb) :: size(1)-big-signed-integer-unit(8), refb :: binary, byte_size(sec_data) :: 1*16-big-signed-integer, sec_data :: binary >> end test :bitsyntax_size_shorcut do assert << 1 :: 3 >> == << 1 :: size(3) >> assert << 1 :: 3*8 >> == << 1 :: size(3)-unit(8) >> end defmacrop signed_16 do quote do big-signed-integer-unit(16) end end defmacrop refb_spec do quote do 1*8-big-signed-integer end end test :bitsyntax_macro do refb = "sample" sec_data = "another" << byte_size(refb) :: refb_spec, refb :: binary, byte_size(sec_data) :: size(1)-signed_16, sec_data :: binary >> end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/case_test.exs000066400000000000000000000023761254730255300254150ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.CaseTest do use ExUnit.Case, async: true test :inline_case do assert (case 1, do: (1 -> :ok; 2 -> :wrong)) == :ok end test :nested_variables do assert vars_case(400, 1) == {400, 1} assert vars_case(401, 1) == {400, -1} assert vars_case(0, -1) == {0, -1} assert vars_case(-1, -1) == {0, 1} end test :nested_vars_match do x = {:error, {:ok, :done}} assert (case x do {:ok, right} -> right {_left, right} -> case right do {:ok, right} -> right end end) == :done end test :in_operator_outside_case do x = 1 y = 4 assert x in [1, 2, 3], "in assertion" assert not y in [1, 2, 3], "not in assertion" end test :in_with_match do refute 1.0 in [1, 2, 3], "not in assertion" end test :in_cond_clause do assert (cond do format() && (f = format()) -> f true -> :text end) == :html end defp format, do: :html defp vars_case(x, vx) do case x > 400 do true -> x = 400 vx = -vx _ -> case x < 0 do true -> x = 0 vx = -vx _ -> nil end end {x, vx} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/char_list_test.exs000066400000000000000000000012031254730255300264360ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule CharListTest do use ExUnit.Case, async: true test :heredoc do assert __ENV__.line == 7 assert 'foo\nbar\n' == ''' foo bar ''' assert __ENV__.line == 13 assert 'foo\nbar \'\'\'\n' == ''' foo bar ''' ''' end test :utf8 do assert length(' ゆんゆん') == 5 end test :hex do assert '\xa' == '\n' assert '\xE9' == 'é' assert '\xfF' == 'ÿ' assert '\x{A}' == '\n' assert '\x{e9}' == 'é' assert '\x{10F}' == [271] assert '\x{10FF}' == [4351] assert '\x{10FFF}' == [69631] assert '\x{10FFFF}' == [1114111] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/cli_test.exs000066400000000000000000000151641254730255300252500ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ import PathHelpers defmodule Kernel.CLI.ARGVTest do use ExUnit.Case, async: true import ExUnit.CaptureIO defp run(argv) do {config, argv} = Kernel.CLI.parse_argv(argv) assert Kernel.CLI.process_commands(config) == [] argv end test "argv handling" do assert capture_io(fn -> assert run(["-e", "IO.puts :ok", "sample.exs", "-o", "1", "2"]) == ["sample.exs", "-o", "1", "2"] end) == "ok\n" assert capture_io(fn -> assert run(["-e", "IO.puts :ok", "--", "sample.exs", "-o", "1", "2"]) == ["sample.exs", "-o", "1", "2"] end) == "ok\n" assert capture_io(fn -> assert run(["-e", "IO.puts :ok", "--hidden", "sample.exs", "-o", "1", "2"]) == ["sample.exs", "-o", "1", "2"] end) == "ok\n" assert capture_io(fn -> assert run(["-e", "IO.puts :ok", "--", "--hidden", "sample.exs", "-o", "1", "2"]) == ["--hidden", "sample.exs", "-o", "1", "2"] end) == "ok\n" end end defmodule Kernel.CLI.OptionParsingTest do use ExUnit.Case, async: true test "properly parses paths" do root = fixture_path("../../..") |> to_char_list list = elixir('-pa "#{root}/*" -pz "#{root}/lib/*" -e "IO.inspect(:code.get_path, limit: :infinity)"') {path, _} = Code.eval_string list, [] # pa assert to_char_list(Path.expand('ebin', root)) in path assert to_char_list(Path.expand('lib', root)) in path assert to_char_list(Path.expand('src', root)) in path # pz assert to_char_list(Path.expand('lib/list', root)) in path end end defmodule Kernel.CLI.AtExitTest do use ExUnit.Case, async: true test "invokes at_exit callbacks" do assert elixir(fixture_path("at_exit.exs") |> to_char_list) == 'goodbye cruel world with status 1\n' end end defmodule Kernel.CLI.ErrorTest do use ExUnit.Case, async: true test "properly format errors" do assert :string.str('** (throw) 1', elixir('-e "throw 1"')) == 0 assert :string.str('** (ErlangError) erlang error: 1', elixir('-e "error 1"')) == 0 assert elixir('-e "IO.puts(Process.flag(:trap_exit, false)); exit({:shutdown, 1})"') == 'false\n' end end defmodule Kernel.CLI.CompileTest do use ExUnit.Case, async: true setup context do # Set up a per-test temporary directory, so we can run these with async: true. # We use the test's line number as the directory name, so they won't conflict. tmp_dir_path = tmp_path("beams/#{context[:line]}") beam_file_path = Path.join([tmp_dir_path, "Elixir.CompileSample.beam"]) fixture = fixture_path "compile_sample.ex" File.mkdir_p!(tmp_dir_path) {:ok, [tmp_dir_path: tmp_dir_path, beam_file_path: beam_file_path, fixture: fixture]} end test "compiles code", context do assert elixirc('#{context[:fixture]} -o #{context[:tmp_dir_path]}') == '' assert File.regular?(context[:beam_file_path]) # Assert that the module is loaded into memory with the proper destination for the BEAM file. Code.append_path context[:tmp_dir_path] assert :code.which(CompileSample) |> List.to_string == Path.expand(context[:beam_file_path]) after Code.delete_path context[:tmp_dir_path] end test "compiles code with verbose mode", context do assert elixirc('#{context[:fixture]} -o #{context[:tmp_dir_path]} --verbose') == 'Compiled #{context[:fixture]}\n' assert File.regular?(context[:beam_file_path]) end test "fails on missing patterns", context do output = elixirc('#{context[:fixture]} non_existing.ex -o #{context[:tmp_dir_path]}') assert :string.str(output, 'non_existing.ex') > 0, "expected non_existing.ex to be mentioned" assert :string.str(output, 'compile_sample.ex') == 0, "expected compile_sample.ex to not be mentioned" refute File.exists?(context[:beam_file_path]), "expected the sample to not be compiled" end test "fails on missing write access to .beam file", context do compilation_args = '#{context[:fixture]} -o #{context[:tmp_dir_path]}' assert elixirc(compilation_args) == '' assert File.regular?(context[:beam_file_path]) # Set the .beam file to read-only File.chmod!(context[:beam_file_path], 4) {:ok, %{access: access}} = File.stat(context[:beam_file_path]) # Can only assert when read-only applies to the user if access != :read_write do output = elixirc(compilation_args) expected = '(File.Error) could not write to ' ++ String.to_char_list(context[:beam_file_path]) ++ ': permission denied' assert :string.str(output, expected) > 0, "expected compilation error message due to not having write access" end end end defmodule Kernel.CLI.ParallelCompilerTest do use ExUnit.Case import ExUnit.CaptureIO test "compiles files solving dependencies" do fixtures = [fixture_path("parallel_compiler/bar.ex"), fixture_path("parallel_compiler/foo.ex")] assert capture_io(fn -> assert [Bar, Foo] = Kernel.ParallelCompiler.files fixtures end) =~ "message_from_foo" after Enum.map [Foo, Bar], fn mod -> :code.purge(mod) :code.delete(mod) end end test "compiles files with structs solving dependencies" do fixtures = [fixture_path("parallel_struct/bar.ex"), fixture_path("parallel_struct/foo.ex")] assert [Bar, Foo] = Kernel.ParallelCompiler.files(fixtures) |> Enum.sort after Enum.map [Foo, Bar], fn mod -> :code.purge(mod) :code.delete(mod) end end test "does not hang on missing dependencies" do fixtures = [fixture_path("parallel_compiler/bat.ex")] assert capture_io(fn -> assert catch_exit(Kernel.ParallelCompiler.files(fixtures)) == {:shutdown, 1} end) =~ "Compilation error" end test "handles possible deadlocks" do fixtures = [fixture_path("parallel_deadlock/foo.ex"), fixture_path("parallel_deadlock/bar.ex")] msg = capture_io(fn -> assert catch_exit(Kernel.ParallelCompiler.files fixtures) == {:shutdown, 1} end) assert msg =~ ~r"== Compilation error on file .+parallel_deadlock/foo\.ex ==" assert msg =~ ~r"== Compilation error on file .+parallel_deadlock/bar\.ex ==" end test "warnings as errors" do warnings_as_errors = Code.compiler_options[:warnings_as_errors] fixtures = [fixture_path("warnings_sample.ex")] try do Code.compiler_options(warnings_as_errors: true) msg = capture_io :stderr, fn -> assert catch_exit(Kernel.ParallelCompiler.files fixtures) == {:shutdown, 1} end assert msg =~ "Compilation failed due to warnings while using the --warnings-as-errors option\n" after Code.compiler_options(warnings_as_errors: warnings_as_errors) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/comprehension_test.exs000066400000000000000000000133741254730255300273530ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.ComprehensionTest do use ExUnit.Case, async: true import ExUnit.CaptureIO require Integer defmodule PDict do defstruct [] defimpl Collectable do def into(struct) do {struct, fn _, {:cont, x} -> Process.put(:into_cont, [x|Process.get(:into_cont)]) _, :done -> Process.put(:into_done, true) _, :halt -> Process.put(:into_halt, true) end} end end end defp to_bin(x) do << x >> end defp nilly, do: nil ## Enum comprehensions (the common case) test "for comprehensions" do enum = 1..3 assert for(x <- enum, do: x * 2) == [2, 4, 6] end test "for comprehensions with matching" do assert for({_, x} <- 1..3, do: x * 2) == [] end test "for comprehensions with filters" do assert for(x <- 1..3, x > 1, x < 3, do: x * 2) == [4] end test "for comprehensions with nilly filters" do assert for(x <- 1..3, nilly, do: x * 2) == [] end test "for comprehensions with errors on filters" do assert_raise ArgumentError, fn -> for(x <- 1..3, hd(x), do: x * 2) end end test "for comprehensions with variables in filters" do assert for(x <- 1..3, y = x + 1, y > 2, z = y, do: x * z) == [6, 12] end test "for comprehensions with two enum generators" do assert (for x <- [1, 2, 3], y <- [4, 5, 6], do: x * y) == [4, 5, 6, 8, 10, 12, 12, 15, 18] end test "for comprehensions with two enum generators and filters" do assert (for x <- [1, 2, 3], y <- [4, 5, 6], y / 2 == x, do: x * y) == [8, 18] end test "for comprehensions generators precedence" do assert (for {_, _} = x <- [foo: :bar], do: x) == [foo: :bar] end test "for comprehensions with binary, enum generators and filters" do assert (for x <- [1, 2, 3], << y <- <<4, 5, 6>> >>, y / 2 == x, do: x * y) == [8, 18] end test "for comprehensions into list" do enum = 1..3 assert for(x <- enum, into: [], do: x * 2) == [2, 4, 6] end test "for comprehensions into binary" do enum = 1..3 assert for(x <- enum, into: "", do: to_bin(x * 2)) == <<2, 4, 6>> end test "for comprehensions where value is not used" do enum = 1..3 assert capture_io(fn -> for(x <- enum, do: IO.puts x) nil end) == "1\n2\n3\n" end test "for comprehensions with into" do Process.put(:into_cont, []) Process.put(:into_done, false) Process.put(:into_halt, false) for x <- 1..3, into: %PDict{} do x * 2 end assert Process.get(:into_cont) == [6, 4, 2] assert Process.get(:into_done) refute Process.get(:into_halt) end test "for comprehension with into leading to errors" do Process.put(:into_cont, []) Process.put(:into_done, false) Process.put(:into_halt, false) catch_error( for x <- 1..3, into: %PDict{} do if x > 2, do: raise("oops"), else: x end ) assert Process.get(:into_cont) == [2, 1] refute Process.get(:into_done) assert Process.get(:into_halt) end test "for comprehension with into, generators and filters" do Process.put(:into_cont, []) for x <- 1..3, Integer.is_odd(x), << y <- "hello" >>, into: %PDict{} do x + y end assert IO.iodata_to_binary(Process.get(:into_cont)) == "roohkpmmfi" end ## List generators (inlined by the compiler) test "list for comprehensions" do list = [1, 2, 3] assert for(x <- list, do: x * 2) == [2, 4, 6] end test "list for comprehensions with matching" do assert for({_, x} <- [1, 2, a: 3, b: 4, c: 5], do: x * 2) == [6, 8, 10] end test "list for comprehension matched to '_' on last line of block" do assert (if true do _ = for x <- [1, 2, 3], do: x * 2 end) == [2, 4, 6] end test "list for comprehensions with filters" do assert for(x <- [1, 2, 3], x > 1, x < 3, do: x * 2) == [4] end test "list for comprehensions with nilly filters" do assert for(x <- [1, 2, 3], nilly, do: x * 2) == [] end test "list for comprehensions with errors on filters" do assert_raise ArgumentError, fn -> for(x <- [1, 2, 3], hd(x), do: x * 2) end end test "list for comprehensions with variables in filters" do assert for(x <- [1, 2, 3], y = x + 1, y > 2, z = y, do: x * z) == [6, 12] end test "list for comprehensions into list" do enum = [1, 2, 3] assert for(x <- enum, into: [], do: x * 2) == [2, 4, 6] end test "list for comprehensions into binaries" do enum = [1, 2, 3] assert for(x <- enum, into: "", do: to_bin(x * 2)) == <<2, 4, 6>> end test "list for comprehensions where value is not used" do enum = [1, 2, 3] assert capture_io(fn -> for(x <- enum, do: IO.puts x) nil end) == "1\n2\n3\n" end ## Binary generators (inlined by the compiler) test "binary for comprehensions" do bin = <<1, 2, 3>> assert for(<< x <- bin >>, do: x * 2) == [2, 4, 6] end test "binary for comprehensions with inner binary" do bin = <<1, 2, 3>> assert for(<< <> <- bin >>, do: x * 2) == [2, 4, 6] end test "binary for comprehensions with two generators" do assert (for << x <- <<1, 2, 3>> >>, << y <- <<4, 5, 6>> >>, y / 2 == x, do: x * y) == [8, 18] end test "binary for comprehensions into list" do bin = <<1, 2, 3>> assert for(<< x <- bin >>, into: [], do: x * 2) == [2, 4, 6] end test "binary for comprehensions into binaries" do bin = <<1, 2, 3>> assert for(<< x <- bin >>, into: "", do: to_bin(x * 2)) == <<2, 4, 6>> end test "binary for comprehensions where value is not used" do bin = <<1, 2, 3>> assert capture_io(fn -> for(<>, do: IO.puts x) nil end) == "1\n2\n3\n" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/docs_test.exs000066400000000000000000000053531254730255300254300ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.DocsTest do use ExUnit.Case test "compiled with docs" do deftestmodule(SampleDocs) docs = Code.get_docs(SampleDocs, :all) assert [{{:__behaviour__, 1}, _, :def, [{:atom, [], Elixir}], false}, {{:argnames, 5}, _, :def, [ {:list1, [], Elixir}, {:list2, [], Elixir}, {:map1, [], Elixir}, {:list3, [], Elixir}, {:map2, [], Elixir}], nil}, {{:fun, 2}, _, :def, [{:x, [], nil}, {:y, [], nil}], "This is fun!\n"}, {{:nofun, 0}, _, :def, [], nil}, {{:sneaky, 1}, _, :def, [{:bool, [], Elixir}], false}, {{:with_defaults, 4}, _, :def, [{:int, [], Elixir}, {:\\, [], [{:x, [], nil}, 0]}, {:\\, [], [{:y, [], nil}, 2015]}, {:\\, [], [{:f, [], nil}, {:&, _, [{:/, _, [{:>=, _, _}, 2]}]}]}], nil}] = docs[:docs] assert {_, "Hello, I am a module"} = docs[:moduledoc] assert [{{:bar, 1}, _, :def, false}, {{:baz, 2}, _, :def, nil}, {{:first, 0}, _, :def, "I should be first."}, {{:foo, 1}, _, :def, "Foo"}, {{:last, 1}, _, :defmacro, "I should be last."}] = docs[:behaviour_docs] end test "compiled without docs" do Code.compiler_options(docs: false) deftestmodule(SampleNoDocs) assert Code.get_docs(SampleNoDocs, :docs) == nil assert Code.get_docs(SampleNoDocs, :moduledoc) == nil assert Code.get_docs(SampleNoDocs, :behaviour_docs) == nil after Code.compiler_options(docs: true) end test "compiled in memory does not have accessible docs" do defmodule NoDocs do @moduledoc "moduledoc" @doc "Some example" def example(var), do: var end assert Code.get_docs(NoDocs, :docs) == nil assert Code.get_docs(NoDocs, :moduledoc) == nil assert Code.get_docs(NoDocs, :behaviour_docs) == nil end defp deftestmodule(name) do import PathHelpers write_beam(defmodule name do @moduledoc "Hello, I am a module" use Behaviour @doc "I should be first." defcallback first :: term @doc "Foo" defcallback foo(any) :: any @doc false defcallback bar(true) :: false defcallback baz(1, binary) :: binary @doc "I should be last." defmacrocallback last(integer) :: Macro.t @doc """ This is fun! """ def fun(x, y) do {x, y} end @doc false def sneaky(true), do: false def nofun() do 'not fun at all' end def argnames([], [], %{}, [], %{}), do: false @year 2015 def with_defaults(@year, x \\ 0, y \\ @year, f \\ &>=/2) do {f, x + y} end end) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/errors_test.exs000066400000000000000000000644311254730255300260160ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.ErrorsTest do use ExUnit.Case, async: true import CompileAssertion defmodule UnproperMacro do defmacro unproper(args), do: args defmacro exit(args), do: args end test :invalid_token do assert_compile_fail SyntaxError, "nofile:1: invalid token: \end", '\end\nlol\nbarbecue' end test :invalid_quoted_token do assert_compile_fail SyntaxError, "nofile:1: syntax error before: \"world\"", '"hello" "world"' assert_compile_fail SyntaxError, "nofile:1: syntax error before: Foobar", '1 Foobar' assert_compile_fail SyntaxError, "nofile:1: syntax error before: foo", 'Foo.:foo' assert_compile_fail SyntaxError, "nofile:1: syntax error before: \"foo\"", 'Foo.:"foo\#{:bar}"' assert_compile_fail SyntaxError, "nofile:1: syntax error before: \"", 'Foo.:"\#{:bar}"' end test :invalid_identifier do msg = fn char, name -> "nofile:1: invalid character '#{char}' in identifier: #{name}" end assert_compile_fail SyntaxError, msg.(:@, "foo@"), 'foo@' assert_compile_fail SyntaxError, msg.(:@, "foo@"), 'foo@ ' assert_compile_fail SyntaxError, msg.(:@, "foo@bar"), 'foo@bar' assert_compile_fail SyntaxError, msg.(:!, "Foo!"), 'Foo!' end test :kw_missing_space do msg = "nofile:1: keyword argument must be followed by space after: foo:" assert_compile_fail SyntaxError, msg, "foo:bar" assert_compile_fail SyntaxError, msg, "foo:+" assert_compile_fail SyntaxError, msg, "foo:+1" end test :invalid_or_reserved_codepoint do assert_compile_fail ArgumentError, "invalid or reserved unicode codepoint 55296", '?\\x{D800}' end test :sigil_terminator do assert_compile_fail TokenMissingError, "nofile:3: missing terminator: \" (for sigil ~r\" starting at line 1)", '~r"foo\n\n' assert_compile_fail TokenMissingError, "nofile:3: missing terminator: } (for sigil ~r{ starting at line 1)", '~r{foo\n\n' end test :dot_terminator do assert_compile_fail TokenMissingError, "nofile:1: missing terminator: \" (for function name starting at line 1)", 'foo."bar' end test :string_terminator do assert_compile_fail TokenMissingError, "nofile:1: missing terminator: \" (for string starting at line 1)", '"bar' end test :heredoc_start do assert_compile_fail SyntaxError, "nofile:1: heredoc start must be followed by a new line after \"\"\"", '"""bar\n"""' end test :heredoc_terminator do assert_compile_fail TokenMissingError, "nofile:2: missing terminator: \"\"\" (for heredoc starting at line 1)", '"""\nbar' end test :unexpected_end do assert_compile_fail SyntaxError, "nofile:1: unexpected token: end", '1 end' end test :syntax_error do assert_compile_fail SyntaxError, "nofile:1: syntax error before: '.'", '+.foo' end test :syntax_error_before_sigil do msg = fn x -> "nofile:1: syntax error before: sigil ~s starting with content '#{x}'" end assert_compile_fail SyntaxError, msg.("bar baz"), '~s(foo) ~s(bar baz)' assert_compile_fail SyntaxError, msg.(""), '~s(foo) ~s()' assert_compile_fail SyntaxError, msg.("bar "), '~s(foo) ~s(bar \#{:baz})' assert_compile_fail SyntaxError, msg.(""), '~s(foo) ~s(\#{:bar} baz)' end test :compile_error_on_op_ambiguity do msg = "nofile:1: \"a -1\" looks like a function call but there is a variable named \"a\", " <> "please use explicit parentheses or even spaces" assert_compile_fail CompileError, msg, 'a = 1; a -1' max = 1 assert max == 1 assert (max 1, 2) == 2 end test :syntax_error_on_parens_call do msg = "nofile:1: unexpected parentheses. If you are making a function call, do not " <> "insert spaces between the function name and the opening parentheses. " <> "Syntax error before: '('" assert_compile_fail SyntaxError, msg, 'foo (hello, world)' end test :syntax_error_on_nested_no_parens_call do msg = "nofile:1: unexpected comma. Parentheses are required to solve ambiguity in " <> "nested calls. Syntax error before: ','" assert_compile_fail SyntaxError, msg, '[foo 1, 2]' assert_compile_fail SyntaxError, msg, '[foo bar 1, 2]' assert_compile_fail SyntaxError, msg, '[do: foo 1, 2]' assert_compile_fail SyntaxError, msg, 'foo(do: bar 1, 2)' assert_compile_fail SyntaxError, msg, '{foo 1, 2}' assert_compile_fail SyntaxError, msg, '{foo bar 1, 2}' assert_compile_fail SyntaxError, msg, 'foo 1, foo 2, 3' assert_compile_fail SyntaxError, msg, 'foo 1, @bar 3, 4' assert_compile_fail SyntaxError, msg, 'foo 1, 2 + bar 3, 4' assert_compile_fail SyntaxError, msg, 'foo(1, foo 2, 3)' assert is_list List.flatten [1] assert is_list Enum.reverse [3, 2, 1], [4, 5, 6] assert is_list(Enum.reverse [3, 2, 1], [4, 5, 6]) assert false || is_list Enum.reverse [3, 2, 1], [4, 5, 6] assert [List.flatten List.flatten [1]] == [[1]] interpret = fn x -> Macro.to_string Code.string_to_quoted! x end assert interpret.("f 1 + g h 2, 3") == "f(1 + g(h(2, 3)))" assert interpret.("assert [] = TestRepo.all from p in Post, where: p.title in ^[]") == "assert([] = TestRepo.all(from(p in Post, where: p.title() in ^[])))" end test :syntax_error_on_atom_dot_alias do msg = "nofile:1: atom cannot be followed by an alias. If the '.' was meant to be " <> "part of the atom's name, the name must be quoted. Syntax error before: '.'" assert_compile_fail SyntaxError, msg, ':foo.Bar' assert_compile_fail SyntaxError, msg, ':"foo".Bar' end test :syntax_error_with_no_token do assert_compile_fail TokenMissingError, "nofile:1: missing terminator: ) (for \"(\" starting at line 1)", 'case 1 (' end test :clause_with_defaults do assert_compile_fail CompileError, "nofile:3: def hello/1 has default values and multiple clauses, " <> "define a function head with the defaults", ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults1 do def hello(arg \\ 0), do: nil def hello(arg \\ 1), do: nil end ''' assert_compile_fail CompileError, "nofile:6: def hello/1 has default values and multiple clauses, " <> "define a function head with the defaults", ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults2 do def bye(arg \\ 0) def bye(arg), do: arg def hello(arg \\ 0), do: nil def hello(arg), do: arg end ''' assert_compile_fail CompileError, "nofile:2: function foo/0 undefined", ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults3 do def hello(foo, bar \\ foo) def hello(foo, bar), do: foo + bar end ''' end test :invalid_match_pattern do assert_compile_fail CompileError, "nofile:2: invalid expression in match", ''' case true do true && true -> true end ''' end test :different_defs_with_defaults do assert_compile_fail CompileError, "nofile:3: def hello/3 defaults conflicts with def hello/2", ~C''' defmodule Kernel.ErrorsTest.DifferentDefsWithDefaults1 do def hello(a, b \\ nil), do: a + b def hello(a, b \\ nil, c \\ nil), do: a + b + c end ''' assert_compile_fail CompileError, "nofile:3: def hello/2 conflicts with defaults from def hello/3", ~C''' defmodule Kernel.ErrorsTest.DifferentDefsWithDefaults2 do def hello(a, b \\ nil, c \\ nil), do: a + b + c def hello(a, b \\ nil), do: a + b end ''' end test :bad_form do assert_compile_fail CompileError, "nofile:2: function bar/0 undefined", ''' defmodule Kernel.ErrorsTest.BadForm do def foo, do: bar end ''' end test :unbound_var do assert_compile_fail CompileError, "nofile:1: unbound variable ^x", '^x = 1' end test :unbound_not_match do assert_compile_fail CompileError, "nofile:1: cannot use ^x outside of match clauses", '^x' end test :unbound_expr do assert_compile_fail CompileError, "nofile:1: invalid argument for unary operator ^, expected an existing variable, got: ^is_atom(:foo)", '^is_atom(:foo) = true' end test :literal_on_map_and_struct do assert_compile_fail SyntaxError, "nofile:1: syntax error before: '}'", '%{{:a, :b}}' assert_compile_fail SyntaxError, "nofile:1: syntax error before: '{'", '%{:a, :b}{a: :b}' assert_compile_fail CompileError, "nofile:1: expected key-value pairs in a map, got: put_in(foo.bar().baz(), nil)", 'foo = 1; %{put_in(foo.bar.baz, nil), :bar}' end test :struct_fields_on_defstruct do assert_compile_fail ArgumentError, "struct field names must be atoms, got: 1", ''' defmodule Kernel.ErrorsTest.StructFieldsOnDefstruct do defstruct [1, 2, 3] end ''' end test :struct_access_on_body do assert_compile_fail CompileError, "nofile:3: cannot access struct Kernel.ErrorsTest.StructAccessOnBody, " <> "the struct was not yet defined or the struct " <> "is being accessed in the same context that defines it", ''' defmodule Kernel.ErrorsTest.StructAccessOnBody do defstruct %{name: "Brasilia"} %Kernel.ErrorsTest.StructAccessOnBody{} end ''' end test :unbound_map_key_var do assert_compile_fail CompileError, "nofile:1: illegal use of variable x in map key", '%{x => 1} = %{}' assert_compile_fail CompileError, "nofile:1: illegal use of variable x in map key", '%{x = 1 => 1}' end test :struct_errors do assert_compile_fail CompileError, "nofile:1: BadStruct.__struct__/0 is undefined, cannot expand struct BadStruct", '%BadStruct{}' defmodule BadStruct do def __struct__ do [] end end assert_compile_fail CompileError, "nofile:1: expected Kernel.ErrorsTest.BadStruct.__struct__/0 to return a map, got: []", '%#{BadStruct}{}' defmodule GoodStruct do def __struct__ do %{name: "john"} end end assert_compile_fail CompileError, "nofile:1: unknown key :age for struct Kernel.ErrorsTest.GoodStruct", '%#{GoodStruct}{age: 27}' end test :name_for_defmodule do assert_compile_fail CompileError, "nofile:1: invalid module name: 3", 'defmodule 1 + 2, do: 3' end test :invalid_unquote do assert_compile_fail CompileError, "nofile:1: unquote called outside quote", 'unquote 1' end test :invalid_unquote_splicing_in_oneliners do assert_compile_fail ArgumentError, "unquote_splicing only works inside arguments and block contexts, " <> "wrap it in parens if you want it to work with one-liners", ''' defmodule Kernel.ErrorsTest.InvalidUnquoteSplicingInOneliners do defmacro oneliner2 do quote do: unquote_splicing 1 end def callme do oneliner2 end end ''' end test :invalid_quote_args do assert_compile_fail CompileError, "nofile:1: invalid arguments for quote", 'quote 1' assert_compile_fail CompileError, "nofile:1: invalid options for quote, expected a keyword list", ''' quote :foo do foo end ''' end test :invalid_calls do assert_compile_fail CompileError, "nofile:1: invalid call foo(1)(2)", 'foo(1)(2)' assert_compile_fail CompileError, "nofile:1: invalid call 1.foo()", '1.foo' end test :unhandled_stab do assert_compile_fail CompileError, "nofile:3: unhandled operator ->", ''' defmodule Kernel.ErrorsTest.UnhandledStab do def fun do casea foo, do: (bar -> baz) end end ''' end test :undefined_non_local_function do assert_compile_fail CompileError, "nofile:1: undefined function casea/2", 'casea foo, do: @hello :world' end test :invalid_attribute do msg = ~r"cannot inject attribute @foo into function/macro because cannot escape " assert_raise ArgumentError, msg, fn -> defmodule InvalidAttribute do @foo fn -> end def bar, do: @foo end end end test :invalid_struct_field_value do msg = ~r"invalid value for struct field baz, cannot escape " assert_raise ArgumentError, msg, fn -> defmodule InvaliadStructFieldValue do defstruct baz: fn -> end end end end test :match_attribute_in_module do msg = "invalid write attribute syntax, you probably meant to use: @foo expression" assert_raise ArgumentError, msg, fn -> defmodule MatchAttributeInModule do @foo = 42 end end end test :invalid_fn_args do assert_compile_fail TokenMissingError, "nofile:1: missing terminator: end (for \"fn\" starting at line 1)", 'fn 1' end test :invalid_escape do assert_compile_fail TokenMissingError, "nofile:1: invalid escape \\ at end of file", '1 \\' end test :function_local_conflict do assert_compile_fail CompileError, "nofile:1: imported Kernel.&&/2 conflicts with local function", ''' defmodule Kernel.ErrorsTest.FunctionLocalConflict do def other, do: 1 && 2 def _ && _, do: :error end ''' end test :macro_local_conflict do assert_compile_fail CompileError, "nofile:6: call to local macro &&/2 conflicts with imported Kernel.&&/2, " <> "please rename the local macro or remove the conflicting import", ''' defmodule Kernel.ErrorsTest.MacroLocalConflict do def hello, do: 1 || 2 defmacro _ || _, do: :ok defmacro _ && _, do: :error def world, do: 1 && 2 end ''' end test :macro_with_undefined_local do assert_compile_fail UndefinedFunctionError, "undefined function: Kernel.ErrorsTest.MacroWithUndefinedLocal.unknown/1 " <> "(function unknown/1 is not available)", ''' defmodule Kernel.ErrorsTest.MacroWithUndefinedLocal do defmacrop bar, do: unknown(1) def baz, do: bar() end ''' end test :private_macro do assert_compile_fail UndefinedFunctionError, "undefined function: Kernel.ErrorsTest.PrivateMacro.foo/0 (function foo/0 is not available)", ''' defmodule Kernel.ErrorsTest.PrivateMacro do defmacrop foo, do: 1 defmacro bar, do: __MODULE__.foo defmacro baz, do: bar end ''' end test :function_definition_with_alias do assert_compile_fail CompileError, "nofile:2: function names should start with lowercase characters or underscore, invalid name Bar", ''' defmodule Kernel.ErrorsTest.FunctionDefinitionWithAlias do def Bar do :baz end end ''' end test :function_import_conflict do assert_compile_fail CompileError, "nofile:3: function exit/1 imported from both :erlang and Kernel, call is ambiguous", ''' defmodule Kernel.ErrorsTest.FunctionImportConflict do import :erlang, warn: false def foo, do: exit(:test) end ''' end test :import_invalid_macro do assert_compile_fail CompileError, "nofile:1: cannot import Kernel.invalid/1 because it doesn't exist", 'import Kernel, only: [invalid: 1]' end test :unrequired_macro do assert_compile_fail SyntaxError, "nofile:2: you must require Kernel.ErrorsTest.UnproperMacro before invoking " <> "the macro Kernel.ErrorsTest.UnproperMacro.unproper/1 " ''' defmodule Kernel.ErrorsTest.UnrequiredMacro do Kernel.ErrorsTest.UnproperMacro.unproper([]) end ''' end test :def_defmacro_clause_change do assert_compile_fail CompileError, "nofile:3: defmacro foo/1 already defined as def", ''' defmodule Kernel.ErrorsTest.DefDefmacroClauseChange do def foo(1), do: 1 defmacro foo(x), do: x end ''' end test :internal_function_overridden do assert_compile_fail CompileError, "nofile:1: function __info__/1 is internal and should not be overridden", ''' defmodule Kernel.ErrorsTest.InternalFunctionOverridden do def __info__(_), do: [] end ''' end test :no_macros do assert_compile_fail CompileError, "nofile:2: could not load macros from module :lists", ''' defmodule Kernel.ErrorsTest.NoMacros do import :lists, only: :macros end ''' end test :invalid_macro do assert_compile_fail CompileError, "nofile: invalid quoted expression: {:foo, :bar, :baz, :bat}", ''' defmodule Kernel.ErrorsTest.InvalidMacro do defmacrop oops do {:foo, :bar, :baz, :bat} end def test, do: oops end ''' end test :unloaded_module do assert_compile_fail CompileError, "nofile:1: module Certainly.Doesnt.Exist is not loaded and could not be found", 'import Certainly.Doesnt.Exist' end test :scheduled_module do assert_compile_fail CompileError, "nofile:4: module Kernel.ErrorsTest.ScheduledModule.Hygiene is not loaded but was defined. " <> "This happens because you are trying to use a module in the same context it is defined. " <> "Try defining the module outside the context that requires it.", ''' defmodule Kernel.ErrorsTest.ScheduledModule do defmodule Hygiene do end import Kernel.ErrorsTest.ScheduledModule.Hygiene end ''' end test :already_compiled_module do assert_compile_fail ArgumentError, "could not call eval_quoted on module Record " <> "because it was already compiled", 'Module.eval_quoted Record, quote(do: 1), [], file: __ENV__.file' end test :interpolation_error do assert_compile_fail SyntaxError, "nofile:1: unexpected token: \")\". \"do\" starting at line 1 is missing terminator \"end\"", '"foo\#{case 1 do )}bar"' end test :in_definition_module do assert_compile_fail CompileError, "nofile:2: cannot define module Kernel.ErrorsTest.InDefinitionModule " <> "because it is currently being defined in nofile:1", ''' defmodule Kernel.ErrorsTest.InDefinitionModule do defmodule Elixir.Kernel.ErrorsTest.InDefinitionModule, do: true end ''' end test :invalid_definition do assert_compile_fail CompileError, "nofile:1: invalid syntax in def 1.(hello)", 'defmodule Kernel.ErrorsTest.InvalidDefinition, do: (def 1.(hello), do: true)' end test :duplicated_bitstring_size do assert_compile_fail CompileError, "nofile:1: duplicated size definition in bitstring", '<<1 :: size(12)-size(13)>>' end test :invalid_bitstring_specified do assert_compile_fail CompileError, "nofile:1: unknown bitstring specifier :atom", '<<1 :: :atom>>' assert_compile_fail CompileError, "nofile:1: unknown bitstring specifier unknown()", '<<1 :: unknown>>' assert_compile_fail CompileError, "nofile:1: unknown bitstring specifier another(12)", '<<1 :: another(12)>>' assert_compile_fail CompileError, "nofile:1: size in bitstring expects an integer or a variable as argument, got: :a", '<<1 :: size(:a)>>' assert_compile_fail CompileError, "nofile:1: unit in bitstring expects an integer as argument, got: :x", '<<1 :: unit(:x)>>' end test :invalid_alias do assert_compile_fail CompileError, "nofile:1: invalid value for keyword :as, expected a simple alias, got nested alias: Sample.Lists", 'alias :lists, as: Sample.Lists' assert_compile_fail CompileError, "nofile:1: invalid argument for alias, expected a compile time atom or alias, got: 1 + 2", 'alias 1 + 2' end test :invalid_alias_expansion do assert_compile_fail CompileError, "nofile:1: an alias must expand to an atom at compilation time, but did not in \"foo.Foo\". " <> "Use Module.concat/2 if you want to dynamically generate aliases", 'foo = :foo; foo.Foo' end test :invalid_import_option do assert_compile_fail CompileError, "nofile:1: unsupported option :ops given to import", 'import :lists, [ops: 1]' end test :invalid_rescue_clause do assert_compile_fail CompileError, "nofile:4: invalid rescue clause. The clause should match on an alias, a variable or be in the `var in [alias]` format", 'try do\n1\nrescue\n%UndefinedFunctionError{arity: 1} -> false\nend' end test :invalid_for_without_generators do assert_compile_fail CompileError, "nofile:1: for comprehensions must start with a generator", 'for is_atom(:foo), do: :foo' end test :invalid_for_bit_generator do assert_compile_fail CompileError, "nofile:1: bitstring fields without size are not allowed in bitstring generators", 'for << x :: binary <- "123" >>, do: x' end test :unbound_cond do assert_compile_fail CompileError, "nofile:1: unbound variable _ inside cond. If you want the last clause to always match, " <> "you probably meant to use: true ->", 'cond do _ -> true end' end test :fun_different_arities do assert_compile_fail CompileError, "nofile:1: cannot mix clauses with different arities in function definition", 'fn x -> x; x, y -> x + y end' end test :end_of_expression do # All valid examples Code.eval_quoted ''' 1; 2; 3 (;) (;1) (1;) (1; 2) fn -> 1; 2 end fn -> ; end if true do ; end try do ; catch _, _ -> ; after ; end ''' # All invalid examples assert_compile_fail SyntaxError, "nofile:1: syntax error before: ';'", '1+;\n2' assert_compile_fail SyntaxError, "nofile:1: syntax error before: ';'", 'max(1, ;2)' end test :new_line_error do assert_compile_fail SyntaxError, "nofile:3: syntax error before: eol", 'if true do\n foo = [],\n baz\nend' end test :invalid_var_or_function_on_guard do assert_compile_fail CompileError, "nofile:4: unknown variable something_that_does_not_exist or " <> "cannot invoke local something_that_does_not_exist/0 inside guard", ''' defmodule Kernel.ErrorsTest.InvalidVarOrFunctionOnGuard do def bar do case [] do [] when something_that_does_not_exist == [] -> :ok end end end ''' end test :bodyless_function_with_guard do assert_compile_fail CompileError, "nofile:2: missing do keyword in def", ''' defmodule Kernel.ErrorsTest.BodyessFunctionWithGuard do def foo(n) when is_number(n) end ''' end test :invalid_args_for_bodyless_clause do assert_compile_fail CompileError, "nofile:2: can use only variables and \\\\ as arguments of bodyless clause", ''' defmodule Kernel.ErrorsTest.InvalidArgsForBodylessClause do def foo(arg // nil) def foo(_), do: :ok end ''' end test :invalid_function_on_match do assert_compile_fail CompileError, "nofile:3: cannot invoke local something_that_does_not_exist/0 inside match", ''' defmodule Kernel.ErrorsTest.InvalidFunctionOnMatch do def fun do case [] do; something_that_does_not_exist() -> :ok; end end end ''' end test :invalid_remote_on_match do assert_compile_fail CompileError, "nofile:1: cannot invoke remote function Hello.something_that_does_not_exist/0 inside match", 'case [] do; Hello.something_that_does_not_exist() -> :ok; end' end test :invalid_remote_on_guard do assert_compile_fail CompileError, "nofile:1: cannot invoke remote function Hello.something_that_does_not_exist/0 inside guard", 'case [] do; [] when Hello.something_that_does_not_exist == [] -> :ok; end' end test :typespec_errors do assert_compile_fail CompileError, "nofile:2: type foo() undefined", ''' defmodule Kernel.ErrorsTest.TypespecErrors1 do @type omg :: foo end ''' if :erlang.system_info(:otp_release) >= '18' do message = "nofile:2: spec for undefined function omg/0" else message = "nofile:2: spec for undefined function Kernel.ErrorsTest.TypespecErrors2.omg/0" end assert_compile_fail CompileError, message, ''' defmodule Kernel.ErrorsTest.TypespecErrors2 do @spec omg :: atom end ''' end test :bad_unquoting do assert_compile_fail CompileError, "nofile: invalid quoted expression: {:foo, 0, 1}", ''' defmodule Kernel.ErrorsTest.BadUnquoting do def range(unquote({:foo, 0, 1})), do: :ok end ''' end test :macros_error_stacktrace do assert [{:erlang, :+, [1, :foo], _}, {Kernel.ErrorsTest.MacrosErrorStacktrace, :sample, 1, _}|_] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosErrorStacktrace do defmacro sample(num), do: num + :foo def other, do: sample(1) end """) end test :macros_function_clause_stacktrace do assert [{__MODULE__, :sample, 1, _}|_] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosFunctionClauseStacktrace do import Kernel.ErrorsTest sample(1) end """) end test :macros_interpreted_function_clause_stacktrace do assert [{Kernel.ErrorsTest.MacrosInterpretedFunctionClauseStacktrace, :sample, 1, _}|_] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosInterpretedFunctionClauseStacktrace do defmacro sample(0), do: 0 def other, do: sample(1) end """) end test :macros_compiled_callback do assert [{Kernel.ErrorsTest, :__before_compile__, [%Macro.Env{module: Kernel.ErrorsTest.MacrosCompiledCallback}], _}|_] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosCompiledCallback do Module.put_attribute(__MODULE__, :before_compile, Kernel.ErrorsTest) end """) end defmacro sample(0), do: 0 defmacro before_compile(_) do quote(do: _) end ## Helpers defp rescue_stacktrace(expr) do result = try do :elixir.eval(to_char_list(expr), []) nil rescue _ -> System.stacktrace end result || raise(ExUnit.AssertionError, message: "Expected function given to rescue_stacktrace to fail") end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/expansion_test.exs000066400000000000000000000365361254730255300265130ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.ExpansionTarget do defmacro seventeen, do: 17 end defmodule Kernel.ExpansionTest do use ExUnit.Case, async: true ## __block__ test "__block__: expands to nil when empty" do assert expand(quote do: __block__()) == nil end test "__block__: expands to argument when arity is 1" do assert expand(quote do: __block__(1)) == 1 end test "__block__: is recursive to argument when arity is 1" do assert expand(quote do: __block__(1, __block__(2))) == quote do: __block__(1, 2) end test "__block__: accumulates vars" do assert expand(quote(do: (a = 1; a))) == quote do: (a = 1; a) end ## alias test "alias: expand args, defines alias and returns itself" do alias true, as: True input = quote do: (alias :hello, as: World, warn: True) {output, env} = expand_env(input, __ENV__) assert output == quote do: (alias :hello, as: :"Elixir.World", warn: true) assert env.aliases == [{:"Elixir.True", true}, {:"Elixir.World", :hello}] end ## __aliases__ test "__aliases__: expands even if no alias" do assert expand(quote do: World) == :"Elixir.World" assert expand(quote do: Elixir.World) == :"Elixir.World" end test "__aliases__: expands with alias" do alias Hello, as: World assert expand_env(quote(do: World), __ENV__) |> elem(0) == :"Elixir.Hello" end test "__aliases__: expands with alias is recursive" do alias Source, as: Hello alias Hello, as: World assert expand_env(quote(do: World), __ENV__) |> elem(0) == :"Elixir.Source" end ## = test "=: sets context to match" do assert expand(quote do: __ENV__.context = :match) == quote do: :match = :match end test "=: defines vars" do {output, env} = expand_env(quote(do: a = 1), __ENV__) assert output == quote(do: a = 1) assert {:a, __MODULE__} in env.vars end test "=: does not carry rhs imports" do assert expand(quote do: (flatten([1, 2, 3]) = import List)) == quote do: (flatten([1, 2, 3]) = import :"Elixir.List", []) end test "=: does not define _" do {output, env} = expand_env(quote(do: _ = 1), __ENV__) assert output == quote(do: _ = 1) assert env.vars == [] end ## Pseudo vars test "__MODULE__" do assert expand(quote do: __MODULE__) == __MODULE__ end test "__DIR__" do assert expand(quote do: __DIR__) == __DIR__ end test "__CALLER__" do assert expand(quote do: __CALLER__) == quote do: __CALLER__ end test "__ENV__" do env = %{__ENV__ | line: 0} assert expand_env(quote(do: __ENV__), env) == {{:%{}, [], Map.to_list(env)}, env} end test "__ENV__.accessor" do env = %{__ENV__ | line: 0} assert expand_env(quote(do: __ENV__.file), env) == {__ENV__.file, env} assert expand_env(quote(do: __ENV__.unknown), env) == {quote(do: unquote({:%{}, [], Map.to_list(env)}).unknown), env} end ## Super test "super: expand args" do assert expand(quote do: super(a, b)) == quote do: super(a(), b()) end ## Vars test "vars: expand to local call" do {output, env} = expand_env(quote(do: a), __ENV__) assert output == quote(do: a()) assert env.vars == [] end test "vars: forces variable to exist" do assert expand(quote do: (var!(a) = 1; var!(a))) message = ~r"expected var \"a\" to expand to an existing variable or be part of a match" assert_raise CompileError, message, fn -> expand(quote do: var!(a)) end message = ~r"expected var \"a\" \(context Unknown\) to expand to an existing variable or be part of a match" assert_raise CompileError, message, fn -> expand(quote do: var!(a, Unknown)) end end test "^: expands args" do assert expand(quote do: ^a = 1) == quote do: ^a = 1 end test "^: raises outside match" do assert_raise CompileError, ~r"cannot use \^a outside of match clauses", fn -> expand(quote do: ^a) end end test "^: raises without var" do assert_raise CompileError, ~r"invalid argument for unary operator \^, expected an existing variable, got: \^1", fn -> expand(quote do: ^1 = 1) end end ## Locals test "locals: expands to remote calls" do assert {{:., _, [Kernel, :=~]}, _, [{:a, _, []}, {:b, _, []}]} = expand(quote do: a =~ b) end test "locals: in guards" do assert expand(quote(do: fn pid when :erlang.==(pid, self) -> pid end)) == quote(do: fn pid when :erlang.==(pid, :erlang.self()) -> pid end) end test "locals: custom imports" do assert expand(quote do: (import Kernel.ExpansionTarget; seventeen)) == quote do: (import :"Elixir.Kernel.ExpansionTarget", []; 17) end ## Tuples test "tuples: expanded as arguments" do assert expand(quote(do: {a = 1, a})) == quote do: {a = 1, a()} assert expand(quote(do: {b, a = 1, a})) == quote do: {b(), a = 1, a()} end ## Maps & structs test "maps: expanded as arguments" do assert expand(quote(do: %{a: a = 1, b: a})) == quote do: %{a: a = 1, b: a()} end test "structs: expanded as arguments" do assert expand(quote(do: %:elixir{a: a = 1, b: a})) == quote do: %:elixir{a: a = 1, b: a()} assert expand(quote(do: %:"Elixir.Kernel"{a: a = 1, b: a})) == quote do: %:"Elixir.Kernel"{a: a = 1, b: a()} end test "structs: expects atoms" do assert_raise CompileError, ~r"expected struct name to be a compile time atom or alias", fn -> expand(quote do: %unknown{a: 1}) end end ## quote test "quote: expanded to raw forms" do assert expand(quote do: (quote do: hello)) == {:{}, [], [:hello, [], __MODULE__]} end ## Anonymous calls test "anonymous calls: expands base and args" do assert expand(quote do: a.(b)) == quote do: a().(b()) end test "anonymous calls: raises on atom base" do assert_raise CompileError, ~r"invalid function call :foo.()", fn -> expand(quote do: :foo.(a)) end end ## Remote calls test "remote calls: expands to erlang" do assert expand(quote do: Kernel.is_atom(a)) == quote do: :erlang.is_atom(a()) end test "remote calls: expands macros" do assert expand(quote do: Kernel.ExpansionTest.thirteen) == 13 end test "remote calls: expands receiver and args" do assert expand(quote do: a.is_atom(b)) == quote do: a().is_atom(b()) assert expand(quote do: (a = :foo).is_atom(a)) == quote do: (a = :foo).is_atom(a()) end test "remote calls: modules must be required for macros" do assert expand(quote do: (require Kernel.ExpansionTarget; Kernel.ExpansionTarget.seventeen)) == quote do: (require :"Elixir.Kernel.ExpansionTarget", []; 17) end test "remote calls: raises when not required" do msg = ~r"you must require Kernel\.ExpansionTarget before invoking the macro Kernel\.ExpansionTarget\.seventeen/0" assert_raise CompileError, msg, fn -> expand(quote do: Kernel.ExpansionTarget.seventeen) end end ## Comprehensions test "variables inside comprehensions do not leak with enums" do assert expand(quote do: (for(a <- b, do: c = 1); c)) == quote do: (for(a <- b(), do: c = 1); c()) end test "variables inside comprehensions do not leak with binaries" do assert expand(quote do: (for(<>, do: c = 1); c)) == quote do: (for(<< <> <- b() >>, do: c = 1); c()) end test "variables inside filters are available in blocks" do assert expand(quote do: for(a <- b, c = a, do: c)) == quote do: (for(a <- b(), c = a, do: c)) end test "variables inside comprehensions options do not leak" do assert expand(quote do: (for(a <- c = b, into: [], do: 1); c)) == quote do: (for(a <- c = b(), do: 1, into: []); c()) assert expand(quote do: (for(a <- b, into: c = [], do: 1); c)) == quote do: (for(a <- b(), do: 1, into: c = []); c()) end ## Capture test "&: keeps locals" do assert expand(quote do: &unknown/2) == {:&, [], [{:/, [], [{:unknown, [], nil}, 2]}]} assert expand(quote do: &unknown(&1, &2)) == {:&, [], [{:/, [], [{:unknown, [], nil}, 2]}]} end test "&: expands remotes" do assert expand(quote do: &List.flatten/2) == quote do: :erlang.make_fun(:"Elixir.List", :flatten, 2) assert expand(quote do: &Kernel.is_atom/1) == quote do: :erlang.make_fun(:erlang, :is_atom, 1) end test "&: expands macros" do assert expand(quote do: (require Kernel.ExpansionTarget; &Kernel.ExpansionTarget.seventeen/0)) == quote do: (require :"Elixir.Kernel.ExpansionTarget", []; fn -> 17 end) end ## fn test "fn: expands each clause" do assert expand(quote do: fn x -> x; _ -> x end) == quote do: fn x -> x; _ -> x() end end test "fn: does not share lexical scope between clauses" do assert expand(quote do: fn 1 -> import List; 2 -> flatten([1, 2, 3]) end) == quote do: fn 1 -> import :"Elixir.List", []; 2 -> flatten([1, 2, 3]) end end test "fn: expands guards" do assert expand(quote do: fn x when x when __ENV__.context -> true end) == quote do: fn x when x when :guard -> true end end test "fn: does not leak vars" do assert expand(quote do: (fn x -> x end; x)) == quote do: (fn x -> x end; x()) end ## Cond test "cond: expands each clause" do assert expand_and_clean(quote do: (cond do x = 1 -> x; _ -> x end)) == quote do: (cond do x = 1 -> x; _ -> x() end) end test "cond: does not share lexical scope between clauses" do assert expand_and_clean(quote do: (cond do 1 -> import List; 2 -> flatten([1, 2, 3]) end)) == quote do: (cond do 1 -> import :"Elixir.List", []; 2 -> flatten([1, 2, 3]) end) end test "cond: does not leaks vars on head" do assert expand_and_clean(quote do: (cond do x = 1 -> x; y = 2 -> y end; :erlang.+(x, y))) == quote do: (cond do x = 1 -> x; y = 2 -> y end; :erlang.+(x(), y())) end test "cond: leaks vars" do assert expand_and_clean(quote do: (cond do 1 -> x = 1; 2 -> y = 2 end; :erlang.+(x, y))) == quote do: (cond do 1 -> x = 1; 2 -> y = 2 end; :erlang.+(x, y)) end ## Case test "case: expands each clause" do assert expand_and_clean(quote do: (case w do x -> x; _ -> x end)) == quote do: (case w() do x -> x; _ -> x() end) end test "case: does not share lexical scope between clauses" do assert expand_and_clean(quote do: (case w do 1 -> import List; 2 -> flatten([1, 2, 3]) end)) == quote do: (case w() do 1 -> import :"Elixir.List", []; 2 -> flatten([1, 2, 3]) end) end test "case: expands guards" do assert expand_and_clean(quote do: (case w do x when x when __ENV__.context -> true end)) == quote do: (case w() do x when x when :guard -> true end) end test "case: does not leaks vars on head" do assert expand_and_clean(quote do: (case w do x -> x; y -> y end; :erlang.+(x, y))) == quote do: (case w() do x -> x; y -> y end; :erlang.+(x(), y())) end test "case: leaks vars" do assert expand_and_clean(quote do: (case w do x -> x = x; y -> y = y end; :erlang.+(x, y))) == quote do: (case w() do x -> x = x; y -> y = y end; :erlang.+(x, y)) end ## Receive test "receive: expands each clause" do assert expand_and_clean(quote do: (receive do x -> x; _ -> x end)) == quote do: (receive do x -> x; _ -> x() end) end test "receive: does not share lexical scope between clauses" do assert expand_and_clean(quote do: (receive do 1 -> import List; 2 -> flatten([1, 2, 3]) end)) == quote do: (receive do 1 -> import :"Elixir.List", []; 2 -> flatten([1, 2, 3]) end) end test "receive: expands guards" do assert expand_and_clean(quote do: (receive do x when x when __ENV__.context -> true end)) == quote do: (receive do x when x when :guard -> true end) end test "receive: does not leaks clause vars" do assert expand_and_clean(quote do: (receive do x -> x; y -> y end; :erlang.+(x, y))) == quote do: (receive do x -> x; y -> y end; :erlang.+(x(), y())) end test "receive: leaks vars" do assert expand_and_clean(quote do: (receive do x -> x = x; y -> y = y end; :erlang.+(x, y))) == quote do: (receive do x -> x = x; y -> y = y end; :erlang.+(x, y)) end test "receive: leaks vars on after" do assert expand_and_clean(quote do: (receive do x -> x = x after y -> y; w = y end; :erlang.+(x, w))) == quote do: (receive do x -> x = x after y() -> y(); w = y() end; :erlang.+(x, w)) end ## Try test "try: expands catch" do assert expand(quote do: (try do x catch x, y -> z = :erlang.+(x, y) end; z)) == quote do: (try do x() catch x, y -> z = :erlang.+(x, y) end; z()) end test "try: expands after" do assert expand(quote do: (try do x after z = y end; z)) == quote do: (try do x() after z = y() end; z()) end test "try: expands else" do assert expand(quote do: (try do x else z -> z end; z)) == quote do: (try do x() else z -> z end; z()) end test "try: expands rescue" do assert expand(quote do: (try do x rescue x -> x; Error -> x end; x)) == quote do: (try do x() rescue unquote(:in)(x, _) -> x; unquote(:in)(_, [:"Elixir.Error"]) -> x() end; x()) end test "try: expects more than do" do assert_raise CompileError, ~r"missing catch/rescue/after/else keyword in try", fn -> expand(quote do: (try do x = y end; x)) end end ## Binaries test "bitstrings: size * unit" do import Kernel, except: [-: 2] assert expand(quote do: << x :: 13 >>) == quote do: << x() :: size(13) >> assert expand(quote do: << x :: 13 * 6 >>) == quote do: << x() :: unit(6)-size(13) >> assert expand(quote do: << x :: _ * 6 >>) == quote do: << x() :: unit(6) >> assert expand(quote do: << x :: 13 * 6 - binary >>) == quote do: << x() :: unit(6)-binary()-size(13) >> assert expand(quote do: << x :: binary - 13 * 6 >>) == quote do: << x() :: binary()-unit(6)-size(13) >> end test "bitstrings: expands modifiers" do assert expand(quote do: (import Kernel.ExpansionTarget; << x :: seventeen >>)) == quote do: (import :"Elixir.Kernel.ExpansionTarget", []; << x() :: size(17) >>) assert expand(quote do: (import Kernel.ExpansionTarget; << seventeen :: seventeen, x :: size(seventeen) >> = 1)) == quote do: (import :"Elixir.Kernel.ExpansionTarget", []; << seventeen :: size(17), x :: size(seventeen) >> = 1) end test "bitstrings: expands modifiers args" do assert expand(quote do: (require Kernel.ExpansionTarget; << x :: size(Kernel.ExpansionTarget.seventeen) >>)) == quote do: (require :"Elixir.Kernel.ExpansionTarget", []; << x() :: size(17) >>) end ## Invalid test "handles invalid expressions" do assert_raise CompileError, ~r"invalid quoted expression: {1, 2, 3}", fn -> expand(quote do: unquote({1, 2, 3})) end assert_raise CompileError, ~r"invalid quoted expression: #Function<", fn -> expand(quote do: unquote({:sample, fn -> end})) end end ## Helpers defmacro thirteen do 13 end defp expand_and_clean(expr) do cleaner = &Keyword.drop(&1, [:export]) expr |> expand_env(__ENV__) |> elem(0) |> Macro.prewalk(&Macro.update_meta(&1, cleaner)) end defp expand(expr) do expand_env(expr, __ENV__) |> elem(0) end defp expand_env(expr, env) do :elixir_exp.expand(expr, env) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/fn_test.exs000066400000000000000000000104501254730255300250750ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.FnTest do use ExUnit.Case, async: true import CompileAssertion test "arithmetic constants on match" do assert (fn 1 + 2 -> :ok end).(3) == :ok assert (fn 1 - 2 -> :ok end).(-1) == :ok assert (fn -1 -> :ok end).(-1) == :ok assert (fn +1 -> :ok end).(1) == :ok end test "capture with access" do assert (&(&1[:hello])).([hello: :world]) == :world end test "capture remote" do assert (&:erlang.atom_to_list/1).(:a) == 'a' assert (&Atom.to_char_list/1).(:a) == 'a' assert (&List.flatten/1).([[0]]) == [0] assert (&(List.flatten/1)).([[0]]) == [0] assert (&List.flatten(&1)).([[0]]) == [0] assert (&List.flatten(&1)) == (&List.flatten/1) end test "capture local" do assert (&atl/1).(:a) == 'a' assert (&(atl/1)).(:a) == 'a' assert (&atl(&1)).(:a) == 'a' end test "capture local with question mark" do assert (&is_a?/2).(:atom, :a) assert (&(is_a?/2)).(:atom, :a) assert (&is_a?(&1, &2)).(:atom, :a) end test "capture imported" do assert (&is_atom/1).(:a) assert (&(is_atom/1)).(:a) assert (&is_atom(&1)).(:a) assert (&is_atom(&1)) == &is_atom/1 end test "capture macro" do assert (&to_string/1).(:a) == "a" assert (&to_string(&1)).(:a) == "a" assert (&Kernel.to_string/1).(:a) == "a" assert (&Kernel.to_string(&1)).(:a) == "a" end test "capture operator" do assert is_function &+/2 assert is_function &(&&/2) assert is_function & &1 + &2, 2 end test "capture with variable module" do mod = List assert (&mod.flatten(&1)).([1, [2], 3]) == [1, 2, 3] assert (&mod.flatten/1).([1, [2], 3]) == [1, 2, 3] assert (&mod.flatten/1) == &List.flatten/1 end test "local partial application" do assert (&atb(&1, :utf8)).(:a) == "a" assert (&atb(List.to_atom(&1), :utf8)).('a') == "a" end test "imported partial application" do import Record assert (&is_record(&1, :sample)).({:sample, 1}) end test "remote partial application" do assert (&:erlang.binary_part(&1, 1, 2)).("foo") == "oo" assert (&:erlang.binary_part(Atom.to_string(&1), 1, 2)).(:foo) == "oo" end test "capture and partially apply tuples" do assert (&{&1, &2}).(1, 2) == {1, 2} assert (&{&1, &2, &3}).(1, 2, 3) == {1, 2, 3} assert (&{1, &1}).(2) == {1, 2} assert (&{1, &1, &2}).(2, 3) == {1, 2, 3} end test "capture and partially apply lists" do assert (&[ &1, &2 ]).(1, 2) == [ 1, 2 ] assert (&[ &1, &2, &3 ]).(1, 2, 3) == [ 1, 2, 3 ] assert (&[ 1, &1 ]).(2) == [ 1, 2 ] assert (&[ 1, &1, &2 ]).(2, 3) == [ 1, 2, 3 ] assert (&[&1|&2]).(1, 2) == [1|2] end test "capture and partially apply on call" do assert (&(&1.module)).(__ENV__) == __MODULE__ end test "capture block like" do assert (&(!is_atom(&1))).(:foo) == false end test "capture other" do assert (& &1).(:ok) == :ok fun = fn a, b -> a + b end assert (&fun.(&1, 2)).(1) == 3 end test "failure on non-continuous" do assert_compile_fail CompileError, "nofile:1: capture &2 cannot be defined without &1", "&(&2)" end test "failure on integers" do assert_compile_fail CompileError, "nofile:1: unhandled &1 outside of a capture", "&1" assert_compile_fail CompileError, "nofile:1: capture &0 is not allowed", "&foo(&0)" end test "failure on block" do assert_compile_fail CompileError, "nofile:1: invalid args for &, block expressions " <> "are not allowed, got: (\n 1\n 2\n)", "&(1;2)" end test "failure on other types" do assert_compile_fail CompileError, "nofile:1: invalid args for &, expected an expression in the format of &Mod.fun/arity, " <> "&local/arity or a capture containing at least one argument as &1, got: :foo", "&:foo" end test "failure when no captures" do assert_compile_fail CompileError, "nofile:1: invalid args for &, expected an expression in the format of &Mod.fun/arity, " <> "&local/arity or a capture containing at least one argument as &1, got: foo()", "&foo()" end defp is_a?(:atom, atom) when is_atom(atom), do: true defp is_a?(_, _), do: false defp atl(arg) do :erlang.atom_to_list(arg) end defp atb(arg, encoding) do :erlang.atom_to_binary(arg, encoding) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/import_test.exs000066400000000000000000000076131254730255300260130ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.ImportTest do use ExUnit.Case, async: true defmodule ImportAvailable do defmacro flatten do [flatten: 1] end end test "import all" do import :lists assert flatten([1, [2], 3]) == [1, 2, 3] end test "import except none" do import :lists, except: [] assert flatten([1, [2], 3]) == [1, 2, 3] end test "import except one" do import :lists, except: [duplicate: 2] assert flatten([1, [2], 3]) == [1, 2, 3] # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end test "import only via macro" do require ImportAvailable import :lists, only: ImportAvailable.flatten assert flatten([1, [2], 3]) == [1, 2, 3] end defmacrop dynamic_opts do [only: [flatten: 1]] end test "import with options via macro" do import :lists, dynamic_opts assert flatten([1, [2], 3]) == [1, 2, 3] end test "import with double except" do import :lists, except: [duplicate: 2] import :lists, except: [each: 2] assert append([1], [2, 3]) == [1, 2, 3] # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end test "import except none respects previous import with except" do import :lists, except: [duplicate: 2] import :lists, except: [] assert append([1], [2, 3]) == [1, 2, 3] # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end test "import except none respects previous import with only" do import :lists, only: [append: 2] import :lists, except: [] assert append([1], [2, 3]) == [1, 2, 3] # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end defmodule Underscored do def hello(x), do: x def __underscore__(x), do: x end defmodule ExplicitUnderscored do def __underscore__(x), do: x * 2 end test "import only with underscore" do import Underscored, only: [__underscore__: 1] assert __underscore__(3) == 3 end test "import non underscored" do import ExplicitUnderscored, only: [__underscore__: 1] import Underscored assert hello(2) == 2 assert __underscore__(3) == 6 end defmodule MessedBitwise do defmacro bnot(x), do: x defmacro bor(x, _), do: x end import Bitwise, only: :macros test "conflicing imports with only and except" do import Bitwise, only: :macros, except: [bnot: 1] import MessedBitwise, only: [bnot: 1] assert bnot(0) == 0 assert bor(0, 1) == 1 end # This test is asserting that the imports in the # test above do not affect this test. test "imports from other functions do not leak" do assert band(1, 1) == 1 assert bor(0, 1) == 1 assert bnot(0) == -1 end test "import ambiguous" do # Simply make sure that we can indeed import functions with # the same name and arity from different modules without the # import itself causing any errors. import List import String end test "import many" do [import(List), import(String)] assert capitalize("foo") == "Foo" assert flatten([1, [2], 3]) == [1, 2, 3] end test "import lexical on if" do if false do import :lists flatten([1, [2], 3]) flunk else # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end end test "import lexical on case" do case true do false -> import :lists flatten([1, [2], 3]) flunk true -> # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end end test "import lexical on try" do try do import :lists flatten([1, [2], 3]) flunk catch _, _ -> # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end # Buggy local duplicate is untouched assert duplicate([1], 2) == [1] end defp duplicate(list, _), do: list end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs000066400000000000000000000034101254730255300276240ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.LexicalTrackerTest do use ExUnit.Case, async: true alias Kernel.LexicalTracker, as: D setup do {:ok, pid} = D.start_link("dest") {:ok, [pid: pid]} end test "gets the destination", config do assert D.dest(config[:pid]) == "dest" end test "can add remote dispatches", config do D.remote_dispatch(config[:pid], String) assert D.remotes(config[:pid]) == [String] end test "can add imports", config do D.add_import(config[:pid], String, 1, true) assert D.remotes(config[:pid]) == [String] end test "can add aliases", config do D.add_alias(config[:pid], String, 1, true) assert D.remotes(config[:pid]) == [String] end test "unused imports", config do D.add_import(config[:pid], String, 1, true) assert D.collect_unused_imports(config[:pid]) == [{String, 1}] end test "used imports are not unused", config do D.add_import(config[:pid], String, 1, true) D.import_dispatch(config[:pid], String) assert D.collect_unused_imports(config[:pid]) == [] end test "imports with no warn are not unused", config do D.add_import(config[:pid], String, 1, false) assert D.collect_unused_imports(config[:pid]) == [] end test "unused aliases", config do D.add_alias(config[:pid], String, 1, true) assert D.collect_unused_aliases(config[:pid]) == [{String, 1}] end test "used aliases are not unused", config do D.add_alias(config[:pid], String, 1, true) D.alias_dispatch(config[:pid], String) assert D.collect_unused_aliases(config[:pid]) == [] end test "aliases with no warn are not unused", config do D.add_alias(config[:pid], String, 1, false) assert D.collect_unused_aliases(config[:pid]) == [] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/macros_test.exs000066400000000000000000000020561254730255300257610ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.MacrosTest.Nested do defmacro value, do: 1 defmacro do_identity!(do: x) do x end end defmodule Kernel.MacrosTest do require Kernel.MacrosTest.Nested, as: Nested use ExUnit.Case, async: true defmacro my_macro do quote do: 1 + 1 end defmacrop my_private_macro do quote do: 1 + 3 end defmacro my_macro_with_default(value \\ 5) do quote do: 1 + unquote(value) end test :require do assert Kernel.MacrosTest.Nested.value == 1 end test :require_with_alias do assert Nested.value == 1 end test :local_but_private_macro do assert my_private_macro == 4 end test :local_with_defaults_macro do assert my_macro_with_default == 6 end test :macros_cannot_be_called_dynamically do x = Nested assert_raise UndefinedFunctionError, fn -> x.value end end test :bang_do_block do import Kernel.MacrosTest.Nested assert (do_identity! do 1 end) == 1 assert (Kernel.MacrosTest.Nested.do_identity! do 1 end) == 1 end endelixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/overridable_test.exs000066400000000000000000000074471254730255300270040ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.Overridable do defmacrop super? do Module.overridable?(__CALLER__.module, __CALLER__.function) end def sample do 1 end def with_super do 1 end def without_super do 1 end def explicit_nested_super do {super?, 2} end false = Module.overridable? __MODULE__, {:explicit_nested_super, 0} defoverridable [sample: 0, with_super: 0, without_super: 0, explicit_nested_super: 0] true = Module.overridable? __MODULE__, {:explicit_nested_super, 0} def explicit_nested_super do {super, super?, 1} end true = Module.overridable? __MODULE__, {:explicit_nested_super, 0} defoverridable [explicit_nested_super: 0] true = Module.overridable? __MODULE__, {:explicit_nested_super, 0} def implicit_nested_super do {super?, 1} end defoverridable [implicit_nested_super: 0] def implicit_nested_super do {super, super?, 0} end def super_with_explicit_args(x, y) do x + y end def many_clauses(0) do 11 end def many_clauses(1) do 13 end defoverridable [implicit_nested_super: 0, super_with_explicit_args: 2, many_clauses: 1] def without_super do :without_super end def with_super do super() + 2 end def no_overridable do {:no_overridable, super?} end def explicit_nested_super do {super, super?, 0} end def super_with_explicit_args(x, y) do super x, y * 2 end def many_clauses(2) do 17 end def many_clauses(3) do super(0) + super(1) end def many_clauses(x) do super(x) end end defmodule Kernel.OverridableTest do defmodule OverridableOrder do def not_private(str) do process_url(str) end defp process_url(_str) do :first end # There was a bug where the order in which we removed # overridable expressions lead to errors. This module # aims to guarantee removing process_url/1 before we # remove the function that depends on it does not cause # errors. If it compiles, it works! defoverridable [process_url: 1, not_private: 1] defp process_url(_str) do :second end end require Kernel.Overridable, as: Overridable use ExUnit.Case, async: true test "overridable is made concrete if no other is defined" do assert Overridable.sample == 1 end test "overridable overridden with super" do assert Overridable.with_super == 3 end test "overridable overridden without super" do assert Overridable.without_super == :without_super end test "overridable overridden with nested super" do assert Overridable.explicit_nested_super == {{{false, 2}, true, 1}, true, 0} end test "overridable node overridden with nested super" do assert Overridable.implicit_nested_super == {{false, 1}, true, 0} end test "calling super with explicit args" do assert Overridable.super_with_explicit_args(1, 2) == 5 end test "function without overridable returns false for super?" do assert Overridable.no_overridable == {:no_overridable, false} end test "overridable with many clauses" do assert Overridable.many_clauses(0) == 11 assert Overridable.many_clauses(1) == 13 assert Overridable.many_clauses(2) == 17 assert Overridable.many_clauses(3) == 24 end test "overridable definitions are private" do refute {:"with_super (overridable 0)", 0} in Overridable.module_info(:exports) end test "invalid super call" do try do :elixir.eval 'defmodule Foo.Forwarding do\ndef bar, do: 1\ndefoverridable [bar: 0]\ndef foo, do: super\nend', [] flunk "expected eval to fail" rescue error -> assert Exception.message(error) == "nofile:4: no super defined for foo/0 in module Foo.Forwarding. " <> "Overridable functions available are: bar/0" end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/quote_test.exs000066400000000000000000000255401254730255300256350ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.QuoteTest do use ExUnit.Case, async: true test :list do assert quote(do: [1, 2, 3]) == [1, 2, 3] end test :tuple do assert quote(do: {:a, 1}) == {:a, 1} end test :keep_line do ## DO NOT MOVE THIS LINE assert quote(location: :keep, do: bar(1, 2, 3)) == {:bar, [file: Path.relative_to_cwd(__ENV__.file), keep: 16], [1, 2, 3]} end test :fixed_line do assert quote(line: 3, do: bar(1, 2, 3)) == {:bar, [line: 3], [1, 2, 3]} end test :quote_line_var do ## DO NOT MOVE THIS LINE line = __ENV__.line assert quote(line: line, do: bar(1, 2, 3)) == {:bar, [line: 26], [1, 2, 3]} end test :unquote_call do assert quote(do: foo(bar)[unquote(:baz)]) == quote(do: foo(bar)[:baz]) assert quote(do: unquote(:bar)()) == quote(do: bar()) assert quote(do: unquote(:bar)(1) do 2 + 3 end) == quote(do: bar(1) do 2 + 3 end) assert quote(do: foo.unquote(:bar)) == quote(do: foo.bar) assert quote(do: foo.unquote(:bar)(1)) == quote(do: foo.bar(1)) assert quote(do: foo.unquote(:bar)(1) do 2 + 3 end) == quote(do: foo.bar(1) do 2 + 3 end) assert quote(do: foo.unquote({:bar, [], nil})) == quote(do: foo.bar) assert quote(do: foo.unquote({:bar, [], [1, 2]})) == quote(do: foo.bar(1, 2)) assert Code.eval_quoted(quote(do: Foo.unquote(Bar))) == {Elixir.Foo.Bar, []} assert Code.eval_quoted(quote(do: Foo.unquote(quote do: Bar))) == {Elixir.Foo.Bar, []} assert_raise ArgumentError, fn -> quote(do: foo.unquote(1)) end end test :nested_quote do assert {:quote, _, [[do: {:unquote, _, _}]]} = quote(do: quote(do: unquote(x))) end defmacrop nested_quote_in_macro do x = 1 quote do x = unquote(x) quote do unquote(x) end end end test :nested_quote_in_macro do assert nested_quote_in_macro == 1 end Enum.each [foo: 1, bar: 2, baz: 3], fn {k, v} -> def unquote(k)(arg) do unquote(v) + arg end end test :dynamic_definition_with_unquote do assert foo(1) == 2 assert bar(2) == 4 assert baz(3) == 6 end test :splice_on_root do contents = [1, 2, 3] assert quote(do: (unquote_splicing(contents))) == quote do: (1; 2; 3) end test :splice_with_tail do contents = [1, 2, 3] assert quote(do: [unquote_splicing(contents)|[1, 2, 3]]) == [1, 2, 3, 1, 2, 3] assert quote(do: [unquote_splicing(contents)|val]) == quote(do: [1, 2, 3 | val]) assert quote(do: [unquote_splicing(contents)|unquote([4])]) == quote(do: [1, 2, 3, 4]) end test :splice_on_stab do {fun, []} = Code.eval_quoted(quote(do: fn(unquote_splicing([1, 2, 3])) -> :ok end), []) assert fun.(1, 2, 3) == :ok {fun, []} = Code.eval_quoted(quote(do: fn(1, unquote_splicing([2, 3])) -> :ok end), []) assert fun.(1, 2, 3) == :ok end test :splice_on_definition do defmodule Hello do def world([unquote_splicing(["foo", "bar"])|rest]) do rest end end assert Hello.world(["foo", "bar", "baz"]) == ["baz"] end test :splice_on_map do assert %{unquote_splicing([foo: :bar])} == %{foo: :bar} assert %{unquote_splicing([foo: :bar]), baz: :bat} == %{foo: :bar, baz: :bat} assert %{unquote_splicing([foo: :bar]), :baz => :bat} == %{foo: :bar, baz: :bat} assert %{:baz => :bat, unquote_splicing([foo: :bar])} == %{foo: :bar, baz: :bat} map = %{foo: :default} assert %{map | unquote_splicing([foo: :bar])} == %{foo: :bar} end test :when do assert [{:->, _, [[{:when, _, [1, 2, 3, 4]}], 5]}] = quote(do: (1, 2, 3 when 4 -> 5)) assert [{:->, _, [[{:when, _, [1, 2, 3, 4]}], 5]}] = quote(do: ((1, 2, 3) when 4 -> 5)) assert [{:->, _, [[{:when, _, [1, 2, 3, {:when, _, [4, 5]}]}], 6]}] = quote(do: ((1, 2, 3) when 4 when 5 -> 6)) end test :stab do assert [{:->, _, [[], nil]}] = (quote do -> end) assert [{:->, _, [[], nil]}] = (quote do: (->)) assert [{:->, _, [[1], nil]}] = (quote do 1 -> end) assert [{:->, _, [[1], nil]}] = (quote do: (1 ->)) assert [{:->, _, [[], 1]}] = (quote do -> 1 end) assert [{:->, _, [[], 1]}] = (quote do: (-> 1)) end test :bind_quoted do assert quote(bind_quoted: [foo: 1 + 2], do: foo) == {:__block__, [], [ {:=, [], [{:foo, [], Kernel.QuoteTest}, 3]}, {:foo, [], Kernel.QuoteTest} ]} end test :literals do assert (quote do: []) == [] assert (quote do: nil) == nil assert (quote do [] end) == [] assert (quote do nil end) == nil end defmacrop dynamic_opts do [line: 3] end test :with_dynamic_opts do assert quote(dynamic_opts, do: bar(1, 2, 3)) == {:bar, [line: 3], [1, 2, 3]} end test :unary_with_integer_precedence do assert quote(do: +1.foo) == quote(do: (+1).foo) assert quote(do: @1.foo) == quote(do: (@1).foo) assert quote(do: &1.foo) == quote(do: (&1).foo) end test :operators_slash_arity do assert {:/, _, [{:+, _, _}, 2]} = quote do: +/2 assert {:/, _, [{:&&, _, _}, 3]} = quote do: &&/3 end test :pipe_precedence do assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo |> bar |> baz) assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo do end |> bar |> baz) assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo |> bar do end |> baz) assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo |> bar |> baz do end) assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo do end |> bar |> baz do end) assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} = quote do: (foo do end |> bar do end |> baz do end) end end ## DO NOT MOVE THIS LINE defmodule Kernel.QuoteTest.Errors do defmacro defadd do quote location: :keep do def add(a, b), do: a + b end end defmacro will_raise do quote location: :keep, do: raise "omg" end end defmodule Kernel.QuoteTest.ErrorsTest do use ExUnit.Case, async: true import Kernel.QuoteTest.Errors # Defines the add function defadd test :inside_function_error do assert_raise ArithmeticError, fn -> add(:a, :b) end mod = Kernel.QuoteTest.ErrorsTest file = __ENV__.file |> Path.relative_to_cwd |> String.to_char_list assert [{^mod, :add, 2, [file: ^file, line: 202]}|_] = System.stacktrace end test :outside_function_error do assert_raise RuntimeError, fn -> will_raise end mod = Kernel.QuoteTest.ErrorsTest file = __ENV__.file |> Path.relative_to_cwd |> String.to_char_list assert [{^mod, _, _, [file: ^file, line: 230]}|_] = System.stacktrace end end defmodule Kernel.QuoteTest.VarHygiene do defmacro no_interference do quote do: a = 1 end defmacro write_interference do quote do: var!(a) = 1 end defmacro read_interference do quote do: 10 = var!(a) end defmacro cross_module_interference do quote do: var!(a, Kernel.QuoteTest.VarHygieneTest) = 1 end end defmodule Kernel.QuoteTest.VarHygieneTest do use ExUnit.Case, async: true import Kernel.QuoteTest.VarHygiene defmacrop cross_module_no_interference do quote do: a = 10 end defmacrop read_cross_module do quote do: var!(a, __MODULE__) end defmacrop nested(var, do: block) do quote do var = unquote(var) unquote(block) var end end defmacrop hat do quote do var = 1 ^var = 1 var end end test :no_interference do a = 10 no_interference assert a == 10 end test :cross_module_interference do cross_module_no_interference cross_module_interference assert read_cross_module == 1 end test :write_interference do write_interference assert a == 1 end test :read_interference do a = 10 read_interference end test :nested do assert (nested 1 do nested 2 do :ok end end) == 1 end test :hat do assert hat == 1 end end defmodule Kernel.QuoteTest.AliasHygiene do alias Dict, as: SuperDict defmacro dict do quote do: Dict.Bar end defmacro super_dict do quote do: SuperDict.Bar end end defmodule Kernel.QuoteTest.AliasHygieneTest do use ExUnit.Case, async: true alias Dict, as: SuperDict test :annotate_aliases do assert {:__aliases__, [alias: false], [:Foo, :Bar]} = quote(do: Foo.Bar) assert {:__aliases__, [alias: false], [:Dict, :Bar]} = quote(do: Dict.Bar) assert {:__aliases__, [alias: Dict.Bar], [:SuperDict, :Bar]} = quote(do: SuperDict.Bar) end test :expand_aliases do assert Code.eval_quoted(quote do: SuperDict.Bar) == {Elixir.Dict.Bar, []} assert Code.eval_quoted(quote do: alias!(SuperDict.Bar)) == {Elixir.SuperDict.Bar, []} end test :expand_aliases_without_macro do alias HashDict, as: SuperDict assert SuperDict.Bar == Elixir.HashDict.Bar end test :expand_aliases_with_macro_does_not_expand_source_alias do alias HashDict, as: Dict, warn: false require Kernel.QuoteTest.AliasHygiene assert Kernel.QuoteTest.AliasHygiene.dict == Elixir.Dict.Bar end test :expand_aliases_with_macro_has_higher_preference do alias HashDict, as: SuperDict, warn: false require Kernel.QuoteTest.AliasHygiene assert Kernel.QuoteTest.AliasHygiene.super_dict == Elixir.Dict.Bar end end defmodule Kernel.QuoteTest.ImportsHygieneTest do use ExUnit.Case, async: true defmacrop get_list_length do quote do length('hello') end end defmacrop get_list_length_with_partial do quote do (&length(&1)).('hello') end end defmacrop get_list_length_with_function do quote do (&length/1).('hello') end end test :expand_imports do import Kernel, except: [length: 1] assert get_list_length == 5 assert get_list_length_with_partial == 5 assert get_list_length_with_function == 5 end defmacrop get_string_length do import Kernel, except: [length: 1] quote do length("hello") end end test :lazy_expand_imports do import Kernel, except: [length: 1] import String, only: [length: 1] assert get_string_length == 5 end test :lazy_expand_imports_no_conflicts do import Kernel, except: [length: 1] import String, only: [length: 1] assert get_list_length == 5 assert get_list_length_with_partial == 5 assert get_list_length_with_function == 5 end defmacrop with_length do quote do import Kernel, except: [length: 1] import String, only: [length: 1] length('hello') end end test :explicitly_overridden_imports do assert with_length == 5 end end defmodule Kernel.QuoteTest.NoQuoteConflictTest do defmacro x |> f do quote do unquote(x) |> unquote(f) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/raise_test.exs000066400000000000000000000177621254730255300256120ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.RaiseTest do use ExUnit.Case, async: true # Silence warnings defp atom, do: RuntimeError defp binary, do: "message" defp opts, do: [message: "message"] defp struct, do: %RuntimeError{message: "message"} @trace [{:foo, :bar, 0, []}] test "raise message" do assert_raise RuntimeError, "message", fn -> raise "message" end assert_raise RuntimeError, "message", fn -> var = binary() raise var end end test "raise with no arguments" do assert_raise RuntimeError, fn -> raise RuntimeError end assert_raise RuntimeError, fn -> var = atom() raise var end end test "raise with arguments" do assert_raise RuntimeError, "message", fn -> raise RuntimeError, message: "message" end assert_raise RuntimeError, "message", fn -> atom = atom() opts = opts() raise atom, opts end end test "raise existing exception" do assert_raise RuntimeError, "message", fn -> raise %RuntimeError{message: "message"} end assert_raise RuntimeError, "message", fn -> var = struct() raise var end end test "reraise message" do try do reraise "message", @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end try do var = binary() reraise var, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end end test "reraise with no arguments" do try do reraise RuntimeError, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end try do var = atom() reraise var, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end end test "reraise with arguments" do try do reraise RuntimeError, [message: "message"], @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end try do atom = atom() opts = opts() reraise atom, opts, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end end test "reraise existing exception" do try do reraise %RuntimeError{message: "message"}, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end try do var = struct() reraise var, @trace flunk "should not reach" rescue RuntimeError -> assert @trace == :erlang.get_stacktrace() end end test :rescue_with_underscore_no_exception do result = try do RescueUndefinedModule.go rescue _ -> true end assert result end test :rescue_with_higher_precedence_than_catch do result = try do RescueUndefinedModule.go catch _, _ -> false rescue _ -> true end assert result end test :rescue_runtime_error do result = try do raise "an exception" rescue RuntimeError -> true catch :error, _ -> false end assert result result = try do raise "an exception" rescue AnotherError -> true catch :error, _ -> false end refute result end test :rescue_named_runtime_error do result = try do raise "an exception" rescue x in [RuntimeError] -> Exception.message(x) catch :error, _ -> false end assert result == "an exception" end test :rescue_argument_error_from_elixir do result = try do raise ArgumentError, "" rescue ArgumentError -> true end assert result end test :rescue_named_with_underscore do result = try do raise "an exception" rescue x in _ -> Exception.message(x) end assert result == "an exception" end test :wrap_custom_erlang_error do result = try do :erlang.error(:sample) rescue x in [RuntimeError, ErlangError] -> Exception.message(x) end assert result == "erlang error: :sample" end test :undefined_function_error do result = try do DoNotExist.for_sure() rescue x in [UndefinedFunctionError] -> Exception.message(x) end assert result == "undefined function: DoNotExist.for_sure/0 (module DoNotExist is not available)" end test :function_clause_error do result = try do zero(1) rescue x in [FunctionClauseError] -> Exception.message(x) end assert result == "no function clause matching in Kernel.RaiseTest.zero/1" end test :badarg_error do result = try do :erlang.error(:badarg) rescue x in [ArgumentError] -> Exception.message(x) end assert result == "argument error" end test :tuple_badarg_error do result = try do :erlang.error({:badarg, [1, 2, 3]}) rescue x in [ArgumentError] -> Exception.message(x) end assert result == "argument error: [1, 2, 3]" end test :badarith_error do result = try do :erlang.error(:badarith) rescue x in [ArithmeticError] -> Exception.message(x) end assert result == "bad argument in arithmetic expression" end test :badarity_error do fun = fn(x) -> x end string = "#{inspect(fun)} with arity 1 called with 2 arguments (1, 2)" result = try do fun.(1, 2) rescue x in [BadArityError] -> Exception.message(x) end assert result == string end test :badfun_error do x = :example result = try do x.(2) rescue x in [BadFunctionError] -> Exception.message(x) end assert result == "expected a function, got: :example" end test :badmatch_error do x = :example result = try do ^x = zero(0) rescue x in [MatchError] -> Exception.message(x) end assert result == "no match of right hand side value: 0" end if :erlang.system_info(:otp_release) >= '18' do test :bad_key_error do result = try do %{%{} | foo: :bar} rescue x in [KeyError] -> Exception.message(x) end assert result == "key :foo not found" result = try do %{}.foo rescue x in [KeyError] -> Exception.message(x) end assert result == "key :foo not found in: %{}" end test :bad_map_error do result = try do %{zero(0) | foo: :bar} rescue x in [BadMapError] -> Exception.message(x) end assert result == "expected a map, got: 0" end end test :case_clause_error do x = :example result = try do case zero(0) do ^x -> nil end rescue x in [CaseClauseError] -> Exception.message(x) end assert result == "no case clause matching: 0" end test :cond_clause_error do result = try do cond do !zero(0) -> :ok end rescue x in [CondClauseError] -> Exception.message(x) end assert result == "no cond clause evaluated to a true value" end test :try_clause_error do f = fn() -> :example end result = try do try do f.() else :other -> :ok end rescue x in [TryClauseError] -> Exception.message(x) end assert result == "no try clause matching: :example" end test :undefined_function_error_as_erlang_error do result = try do DoNotExist.for_sure() rescue x in [ErlangError] -> Exception.message(x) end assert result == "undefined function: DoNotExist.for_sure/0 (module DoNotExist is not available)" end defmacrop exceptions do [ErlangError] end test :with_macros do result = try do DoNotExist.for_sure() rescue x in exceptions -> Exception.message(x) end assert result == "undefined function: DoNotExist.for_sure/0 (module DoNotExist is not available)" end defp zero(0), do: 0 end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/sigils_test.exs000066400000000000000000000053241254730255300257700ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.SigilsTest do use ExUnit.Case, async: true test :sigil_s do assert ~s(foo) == "foo" assert ~s(f#{:o}o) == "foo" assert ~s(f\no) == "f\no" end test :sigil_s_with_heredoc do assert " foo\n\n" == ~s""" f#{:o}o\n """ end test :sigil_S do assert ~S(foo) == "foo" assert ~S[foo] == "foo" assert ~S{foo} == "foo" assert ~S'foo' == "foo" assert ~S"foo" == "foo" assert ~S == "foo" assert ~S/foo/ == "foo" assert ~S|foo| == "foo" assert ~S(f#{o}o) == "f\#{o}o" assert ~S(f\#{o}o) == "f\\\#{o}o" assert ~S(f\no) == "f\\no" assert ~S(foo\)) == "foo)" assert ~S[foo\]] == "foo]" end test :sigil_S_with_heredoc do assert " f\#{o}o\\n\n" == ~S""" f#{o}o\n """ end test :sigil_c do assert ~c(foo) == 'foo' assert ~c(f#{:o}o) == 'foo' assert ~c(f\no) == 'f\no' end test :sigil_C do assert ~C(foo) == 'foo' assert ~C[foo] == 'foo' assert ~C{foo} == 'foo' assert ~C'foo' == 'foo' assert ~C"foo" == 'foo' assert ~C|foo| == 'foo' assert ~C(f#{o}o) == 'f\#{o}o' assert ~C(f\no) == 'f\\no' end test :sigil_w do assert ~w() == [] assert ~w(foo bar baz) == ["foo", "bar", "baz"] assert ~w(foo #{:bar} baz) == ["foo", "bar", "baz"] assert ~w( foo bar baz ) == ["foo", "bar", "baz"] assert ~w(foo bar baz)s == ["foo", "bar", "baz"] assert ~w(foo bar baz)a == [:foo, :bar, :baz] assert ~w(foo bar baz)c == ['foo', 'bar', 'baz'] bad_modifier = quote do: ~w(foo bar baz)x assert %ArgumentError{} = catch_error(Code.eval_quoted(bad_modifier)) assert ~w(Foo Bar)a == [:"Foo", :"Bar"] assert ~w(Foo.#{Bar}.Baz)a == [:"Foo.Elixir.Bar.Baz"] assert ~w(Foo.Bar)s == ["Foo.Bar"] assert ~w(Foo.#{Bar})c == ['Foo.Elixir.Bar'] # Ensure it is fully expanded at compile time assert Macro.expand(quote(do: ~w(a b c)a), __ENV__) == [:a, :b, :c] end test :sigil_W do assert ~W(foo #{bar} baz) == ["foo", "\#{bar}", "baz"] assert ~W( foo bar baz ) == ["foo", "bar", "baz"] assert ~W(foo bar baz)s == ["foo", "bar", "baz"] assert ~W(foo bar baz)a == [:foo, :bar, :baz] assert ~W(foo bar baz)c == ['foo', 'bar', 'baz'] bad_modifier = quote do: ~W(foo bar baz)x assert %ArgumentError{} = catch_error(Code.eval_quoted(bad_modifier)) assert ~W(Foo #{Bar})a == [:"Foo", :"\#{Bar}"] assert ~W(Foo.Bar.Baz)a == [:"Foo.Bar.Baz"] end test :sigils_matching do assert ~s(f\(oo) == "f(oo" assert ~s(fo\)o) == "fo)o" assert ~s(f\(o\)o) == "f(o)o" assert ~s(f[oo) == "f[oo" assert ~s(fo]o) == "fo]o" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/typespec_test.exs000066400000000000000000000466741254730255300263470ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.TypespecTest do use ExUnit.Case, async: true alias Kernel.TypespecTest.TestTypespec defstruct [:hello] # This macro allows us to focus on the result of the # definition and not on the hassles of handling test # module defmacrop test_module([{:do, block}]) do quote do {:module, _, binary, _} = defmodule TestTypespec do unquote(block) end :code.delete(TestTypespec) :code.purge(TestTypespec) binary end end defp types(module) do Kernel.Typespec.beam_types(module) |> Enum.sort end @skip_specs [__info__: 1] defp specs(module) do Kernel.Typespec.beam_specs(module) |> Enum.reject(fn {sign, _} -> sign in @skip_specs end) |> Enum.sort() end defp callbacks(module) do Kernel.Typespec.beam_callbacks(module) |> Enum.sort end test "invalid type specification" do assert_raise CompileError, ~r"invalid type specification: mytype = 1", fn -> test_module do @type mytype = 1 end end end test "unexpected expression in typespec" do assert_raise CompileError, ~r"unexpected expression in typespec: \"foobar\"", fn -> test_module do @type mytype :: "foobar" end end end test "invalid function specification" do assert_raise CompileError, ~r"invalid function type specification: myfun = 1", fn -> test_module do @spec myfun = 1 end end end test "@type with a single type" do module = test_module do @type mytype :: term end assert [type: {:mytype, {:type, _, :term, []}, []}] = types(module) end test "@type with an atom" do module = test_module do @type mytype :: :atom end assert [type: {:mytype, {:atom, _, :atom}, []}] = types(module) end test "@type with an atom alias" do module = test_module do @type mytype :: Atom end assert [type: {:mytype, {:atom, _, Atom}, []}] = types(module) end test "@type with an integer" do module = test_module do @type mytype :: 10 end assert [type: {:mytype, {:integer, _, 10}, []}] = types(module) end test "@type with a negative integer" do module = test_module do @type mytype :: -10 end assert [type: {:mytype, {:op, _, :-, {:integer, _, 10}}, []}] = types(module) end test "@type with a remote type" do module = test_module do @type mytype :: Remote.Some.type @type mytype_arg :: Remote.type(integer) end assert [type: {:mytype, {:remote_type, _, [{:atom, _, Remote.Some}, {:atom, _, :type}, []]}, []}, type: {:mytype_arg, {:remote_type, _, [{:atom, _, Remote}, {:atom, _, :type}, [{:type, _, :integer, []}]]}, []}] = types(module) end test "@type with a binary" do module = test_module do @type mytype :: binary end assert [type: {:mytype, {:type, _, :binary, []}, []}] = types(module) end test "@type with an empty binary" do module = test_module do @type mytype :: <<>> end assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 0}, {:integer, _, 0}]}, []}] = types(module) end test "@type with a binary with a base size" do module = test_module do @type mytype :: <<_ :: 3>> end assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 3}, {:integer, _, 0}]}, []}] = types(module) end test "@type with a binary with a unit size" do module = test_module do @type mytype :: <<_ :: _ * 8>> end assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 0}, {:integer, _, 8}]}, []}] = types(module) end test "@type with a range op" do module = test_module do @type mytype :: 1..10 end assert [type: {:mytype, {:type, _, :range, [{:integer, _, 1}, {:integer, _, 10}]}, []}] = types(module) end test "@type with a map" do module = test_module do @type mytype :: %{hello: :world} end if :erlang.system_info(:otp_release) >= '18' do assert [type: {:mytype, {:type, _, :map, [ {:type, _, :map_field_assoc, [{:atom, _, :hello}, {:atom, _, :world}]} ]}, []}] = types(module) else assert [type: {:mytype, {:type, _, :map, [ {:type, _, :map_field_assoc, {:atom, _, :hello}, {:atom, _, :world}} ]}, []}] = types(module) end end test "@type with a struct" do module = test_module do defstruct [hello: nil, other: nil] @type mytype :: %TestTypespec{hello: :world} end if :erlang.system_info(:otp_release) >= '18' do assert [type: {:mytype, {:type, _, :map, [ {:type, _, :map_field_assoc, [{:atom, _, :__struct__}, {:atom, _, TestTypespec}]}, {:type, _, :map_field_assoc, [{:atom, _, :hello}, {:atom, _, :world}]}, {:type, _, :map_field_assoc, [{:atom, _, :other}, {:type, _, :term, []}]} ]}, []}] = types(module) else assert [type: {:mytype, {:type, _, :map, [ {:type, _, :map_field_assoc, {:atom, _, :__struct__}, {:atom, _, TestTypespec}}, {:type, _, :map_field_assoc, {:atom, _, :hello}, {:atom, _, :world}}, {:type, _, :map_field_assoc, {:atom, _, :other}, {:type, _, :term, []}} ]}, []}] = types(module) end end test "@type with undefined struct" do assert_raise UndefinedFunctionError, fn -> test_module do @type mytype :: %ThisModuleDoesNotExist{} end end assert_raise CompileError, ~r"struct is not defined for TestTypespec", fn -> test_module do @type mytype :: %TestTypespec{} end end end test "@type with a struct with undefined field" do assert_raise CompileError, ~r"undefined field no_field on struct TestTypespec", fn -> test_module do defstruct [hello: nil, eric: nil] @type mytype :: %TestTypespec{no_field: :world} end end end test "@type with public record" do module = test_module do require Record Record.defrecord :timestamp, [date: 1, time: 2] @type mytype :: record(:timestamp, time: :foo) end assert [type: {:mytype, {:type, _, :tuple, [ {:atom, 0, :timestamp}, {:atom, 0, :foo}, {:type, 0, :term, []} ]}, []}] = types(module) end test "@type with private record" do module = test_module do require Record Record.defrecordp :timestamp, [date: 1, time: 2] @type mytype :: record(:timestamp, time: :foo) end assert [type: {:mytype, {:type, _, :tuple, [ {:atom, 0, :timestamp}, {:atom, 0, :foo}, {:type, 0, :term, []} ]}, []}] = types(module) end test "@type with undefined record" do assert_raise CompileError, ~r"unknown record :this_record_does_not_exist", fn -> test_module do @type mytype :: record(:this_record_does_not_exist, []) end end end test "@type with a record with undefined field" do assert_raise CompileError, ~r"undefined field no_field on record :timestamp", fn -> test_module do require Record Record.defrecord :timestamp, [date: 1, time: 2] @type mytype :: record(:timestamp, no_field: :foo) end end end test "@type with list shortcuts" do module = test_module do @type mytype :: [] @type mytype1 :: [integer] @type mytype2 :: [integer, ...] end assert [type: {:mytype, {:type, _, :nil, []}, []}, type: {:mytype1, {:type, _, :list, [{:type, _, :integer, []}]}, []}, type: {:mytype2, {:type, _, :nonempty_list, [{:type, _, :integer, []}]}, []}] = types(module) end test "@type with a fun" do module = test_module do @type mytype :: (... -> any) end assert [type: {:mytype, {:type, _, :fun, []}, []}] = types(module) end test "@type with a fun with multiple arguments and return type" do module = test_module do @type mytype :: (integer, integer -> integer) end assert [type: {:mytype, {:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}, {:type, _, :integer, []}]}, {:type, _, :integer, []}]}, []}] = types(module) end test "@type with a fun with no arguments and return type" do module = test_module do @type mytype :: (() -> integer) end assert [type: {:mytype, {:type, _, :fun, [{:type, _, :product, []}, {:type, _, :integer, []}]}, []}] = types(module) end test "@type with a fun with any arity and return type" do module = test_module do @type mytype :: (... -> integer) end assert [type: {:mytype, {:type, _, :fun, [{:type, _, :any}, {:type, _, :integer, []}]}, []}] = types(module) end test "@type with a union" do module = test_module do @type mytype :: integer | char_list | atom end assert [type: {:mytype, {:type, _, :union, [{:type, _, :integer, []}, {:remote_type, _, [{:atom, _, :elixir}, {:atom, _, :char_list}, []]}, {:type, _, :atom, []}]}, []}] = types(module) end test "@type with keywords" do module = test_module do @type mytype :: [first: integer, step: integer, last: integer] end assert [type: {:mytype, {:type, _, :list, [ {:type, _, :union, [ {:type, _, :tuple, [{:atom, _, :first}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:atom, _, :step}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:atom, _, :last}, {:type, _, :integer, []}]} ]} ]}, []}] = types(module) end test "@type with parameters" do module = test_module do @type mytype(x) :: x @type mytype1(x) :: list(x) @type mytype2(x, y) :: {x, y} end assert [type: {:mytype, {:var, _, :x}, [{:var, _, :x}]}, type: {:mytype1, {:type, _, :list, [{:var, _, :x}]}, [{:var, _, :x}]}, type: {:mytype2, {:type, _, :tuple, [{:var, _, :x}, {:var, _, :y}]}, [{:var, _, :x}, {:var, _, :y}]}] = types(module) end test "@type with annotations" do module = test_module do @type mytype :: (named :: integer) @type mytype1 :: (a :: integer -> integer) end assert [type: {:mytype, {:ann_type, _, [{:var, _, :named}, {:type, _, :integer, []}]}, []}, type: {:mytype1, {:type, _, :fun, [{:type, _, :product, [{:ann_type, _, [{:var, _, :a}, {:type, _, :integer, []}]}]}, {:type, _, :integer, []}]}, []}] = types(module) end test "@opaque(type)" do module = test_module do @opaque mytype(x) :: x end assert [opaque: {:mytype, {:var, _, :x}, [{:var, _, :x}]}] = types(module) end test "@type + opaque" do module = test_module do @type mytype :: tuple @opaque mytype1 :: {} end assert [opaque: {:mytype1, _, []}, type: {:mytype, _, []}, ] = types(module) end test "@type unquote fragment" do module = test_module do quoted = quote unquote: false do name = :mytype type = :atom @type unquote(name)() :: unquote(type) end Module.eval_quoted(__MODULE__, quoted) |> elem(0) end assert [type: {:mytype, {:atom, _, :atom}, []}] = types(module) end test "defines_type?" do test_module do @type mytype :: tuple @type mytype(a) :: [a] assert Kernel.Typespec.defines_type?(__MODULE__, :mytype, 0) assert Kernel.Typespec.defines_type?(__MODULE__, :mytype, 1) refute Kernel.Typespec.defines_type?(__MODULE__, :mytype, 2) end end test "@spec(spec)" do module = test_module do def myfun1(x), do: x def myfun2(), do: :ok def myfun3(x, y), do: {x, y} def myfun4(x), do: x @spec myfun1(integer) :: integer @spec myfun2() :: integer @spec myfun3(integer, integer) :: {integer, integer} @spec myfun4(x :: integer) :: integer end assert [{{:myfun1, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]}, {{:myfun2, 0}, [{:type, _, :fun, [{:type, _, :product, []}, {:type, _, :integer, []}]}]}, {{:myfun3, 2}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:type, _, :integer, []}, {:type, _, :integer, []}]}]}]}, {{:myfun4, 1}, [{:type, _, :fun, [{:type, _, :product, [{:ann_type, _, [{:var, _, :x}, {:type, _, :integer, []}]}]}, {:type, _, :integer, []}]}]}] = specs(module) end test "@spec(spec) for unreachable private function" do # Run it inside capture_io/2 so that the "myfun/1 is unused" # warning doesn't get printed among the ExUnit test results. output = ExUnit.CaptureIO.capture_io :stderr, fn -> module = test_module do defp myfun(x), do: x @spec myfun(integer) :: integer end assert [] == specs(module) end assert output =~ "warning: function myfun/1 is unused" end test "@spec(spec) with guards" do module = test_module do def myfun1(x), do: x @spec myfun1(x) :: boolean when [x: integer] def myfun2(x), do: x @spec myfun2(x) :: x when [x: var] def myfun3(_x, y), do: y @spec myfun3(x, y) :: y when [y: x, x: var] end assert [{{:myfun1, 1}, [{:type, _, :bounded_fun, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}]}, {:type, _, :boolean, []}]}, [{:type, _, :constraint, [{:atom, _, :is_subtype}, [{:var, _, :x}, {:type, _, :integer, []}]]}]]}]}, {{:myfun2, 1}, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}]}, {:var, _, :x}]}]}, {{:myfun3, 2}, [{:type, _, :bounded_fun, [{:type, _, :fun, [{:type, _, :product, [{:var, _, :x}, {:var, _, :y}]}, {:var, _, :y}]}, [{:type, _, :constraint, [{:atom, _, :is_subtype}, [{:var, _, :y}, {:var, _, :x}]]}]]}]}] = specs(module) end test "@callback(callback)" do module = test_module do @callback myfun(integer) :: integer @callback myfun() :: integer @callback myfun(integer, integer) :: {integer, integer} end assert [{{:myfun, 0}, [{:type, _, :fun, [{:type, _, :product, []}, {:type, _, :integer, []}]}]}, {{:myfun, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]}, {{:myfun, 2}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}, {:type, _, :integer, []}]}, {:type, _, :tuple, [{:type, _, :integer, []}, {:type, _, :integer, []}]}]}]}] = callbacks(module) end test "@spec + @callback" do module = test_module do def myfun(x), do: x @spec myfun(integer) :: integer @spec myfun(char_list) :: char_list @callback cb(integer) :: integer end assert [{{:cb, 1}, [{:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]}] = callbacks(module) assert [{{:myfun, 1}, [ {:type, _, :fun, [{:type, _, :product, [ {:remote_type, _, [{:atom, _, :elixir}, {:atom, _, :char_list}, []]}]}, {:remote_type, _, [{:atom, _, :elixir}, {:atom, _, :char_list}, []]}]}, {:type, _, :fun, [{:type, _, :product, [{:type, _, :integer, []}]}, {:type, _, :integer, []}]}]}] = specs(module) end test "block handling" do module = test_module do @spec foo((() -> [ integer ])) :: integer def foo(_), do: 1 end assert [{{:foo, 1}, [{:type, _, :fun, [{:type, _, :product, [ {:type, _, :fun, [{:type, _, :product, []}, {:type, _, :list, [{:type, _, :integer, []}]}]}]}, {:type, _, :integer, []}]}]}] = specs(module) end # Conversion to AST test "type_to_ast" do quoted = [ (quote do: @type with_ann() :: (t :: atom())), (quote do: @type a_tuple() :: tuple()), (quote do: @type empty_tuple() :: {}), (quote do: @type one_tuple() :: {:foo}), (quote do: @type two_tuple() :: {:foo, :bar}), (quote do: @type imm_type_1() :: 1), (quote do: @type imm_type_2() :: :atom), (quote do: @type simple_type() :: integer()), (quote do: @type param_type(p) :: [p]), (quote do: @type union_type() :: integer() | binary() | boolean()), (quote do: @type binary_type1() :: <<_ :: _ * 8>>), (quote do: @type binary_type2() :: <<_ :: 3 * 8>>), (quote do: @type binary_type3() :: <<_ :: 3>>), (quote do: @type tuple_type() :: {integer()}), (quote do: @type ftype() :: (() -> any()) | (() -> integer()) | ((integer() -> integer()))), (quote do: @type cl() :: char_list()), (quote do: @type ab() :: as_boolean(term())), (quote do: @type vaf() :: (... -> any())), (quote do: @type rng() :: 1 .. 10), (quote do: @type opts() :: [first: integer(), step: integer(), last: integer()]), (quote do: @type ops() :: {+1, -1}), (quote do: @type a_map() :: map()), (quote do: @type empty_map() :: %{}), (quote do: @type my_map() :: %{hello: :world}), (quote do: @type my_struct() :: %Kernel.TypespecTest{hello: :world}), (quote do: @type list1() :: list()), (quote do: @type list2() :: [0]), (quote do: @type list3() :: [...]), (quote do: @type list4() :: [0, ...]), (quote do: @type nil_list() :: []), ] |> Enum.sort module = test_module do Module.eval_quoted __MODULE__, quoted end types = types(module) Enum.each(Enum.zip(types, quoted), fn {{:type, type}, definition} -> ast = Kernel.Typespec.type_to_ast(type) assert Macro.to_string(quote do: @type unquote(ast)) == Macro.to_string(definition) end) end test "type_to_ast for paren_type" do type = {:my_type, {:paren_type, 0, [{:type, 0, :integer, []}]}, []} assert Kernel.Typespec.type_to_ast(type) == {:::, [], [{:my_type, [], []}, {:integer, [line: 0], []}]} end test "spec_to_ast" do quoted = [ (quote do: @spec a() :: integer()), (quote do: @spec a(atom()) :: integer() | [{}]), (quote do: @spec a(b) :: integer() when [b: integer()]), (quote do: @spec a(b) :: b when [b: var]), (quote do: @spec a(c :: atom()) :: atom()), ] |> Enum.sort module = test_module do def a, do: 1 def a(a), do: a Module.eval_quoted __MODULE__, quote do: (unquote_splicing(quoted)) end specs = Enum.flat_map(specs(module), fn {{_, _}, specs} -> Enum.map(specs, fn spec -> quote do: @spec unquote(Kernel.Typespec.spec_to_ast(:a, spec)) end) end) |> Enum.sort Enum.each(Enum.zip(specs, quoted), fn {spec, definition} -> assert Macro.to_string(spec) == Macro.to_string(definition) end) end test "typedoc retrieval" do {:module, _, binary, _} = defmodule T do @typedoc "A" @type a :: any @typep b :: any @typedoc "C" @opaque c(x, y) :: {x, y} @type d :: any @spec uses_b() :: b def uses_b(), do: nil end :code.delete(T) :code.purge(T) assert [ {{:c, 2}, "C"}, {{:a, 0}, "A"} ] = Kernel.Typespec.beam_typedocs(binary) end test "retrieval invalid data" do assert Kernel.Typespec.beam_typedocs(Unknown) == nil assert Kernel.Typespec.beam_types(Unknown) == nil assert Kernel.Typespec.beam_specs(Unknown) == nil end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel/warning_test.exs000066400000000000000000000300621254730255300261400ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Kernel.WarningTest do use ExUnit.Case import ExUnit.CaptureIO defp capture_err(fun) do capture_io(:stderr, fun) end test :unused_variable do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def hello(arg), do: nil end """ end) =~ "warning: variable arg is unused" after purge Sample end test :underscored_variable_on_match do assert capture_err(fn -> Code.eval_string """ {_arg, _arg} = {1, 1} """ end) =~ "warning: the underscored variable \"_arg\" appears more than once in a match" end test :unused_function do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do defp hello, do: nil end """ end) =~ "warning: function hello/0 is unused" assert capture_err(fn -> Code.eval_string """ defmodule Sample2 do defp hello(0), do: hello(1) defp hello(1), do: :ok end """ end) =~ "function hello/1 is unused" assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample3 do def a, do: nil def b, do: d(10) defp c(x, y \\ 1), do: [x, y] defp d(x), do: x end """ end) =~ "warning: function c/2 is unused" after purge [Sample1, Sample2, Sample3] end test :unused_cyclic_functions do assert capture_err(fn -> Code.eval_string """ defmodule Sample do defp a, do: b defp b, do: a end """ end) =~ "warning: function a/0 is unused" after purge Sample end test :unused_macro do assert capture_err(fn -> Code.eval_string """ defmodule Sample do defmacrop hello, do: nil end """ end) =~ "warning: macro hello/0 is unused" after purge Sample end test :shadowing do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def test(x) do case x do {:file, fid} -> fid {:path, _} -> fn(fid) -> fid end end end end """ end) == "" after purge Sample end test :unused_default_args do assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample1 do def a, do: b(1, 2, 3) defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """ end) =~ "warning: default arguments in b/3 are never used" assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample2 do def a, do: b(1, 2) defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """ end) =~ "warning: the first 2 default arguments in b/3 are never used" assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample3 do def a, do: b(1) defp b(arg1 \\ 1, arg2 \\ 2, arg3 \\ 3), do: [arg1, arg2, arg3] end """ end) =~ "warning: the first default argument in b/3 is never used" assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample4 do def a, do: b(1) defp b(arg1 \\ 1, arg2, arg3 \\ 3), do: [arg1, arg2, arg3] end """ end) == "" after purge [Sample1, Sample2, Sample3, Sample4] end test :unused_import do assert capture_err(fn -> Code.compile_string """ defmodule Sample do import :lists, only: [flatten: 1] def a, do: nil end """ end) =~ "warning: unused import :lists" assert capture_err(fn -> Code.compile_string """ import :lists, only: [flatten: 1] """ end) =~ "warning: unused import :lists" after purge Sample end test :unused_alias do assert capture_err(fn -> Code.compile_string """ defmodule Sample do alias :lists, as: List def a, do: nil end """ end) =~ "warning: unused alias List" after purge Sample end test :unused_inside_dynamic_module do import List, only: [flatten: 1], warn: false assert capture_err(fn -> defmodule Sample do import String, only: [downcase: 1] def world do flatten([1, 2, 3]) end end end) =~ "warning: unused import String" after purge Sample end test :unused_guard do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do def is_atom_case do v = "bc" case v do _ when is_atom(v) -> :ok _ -> :fail end end end """ end) =~ "nofile:5: warning: this check/guard will always yield the same result" assert capture_err(fn -> Code.eval_string """ defmodule Sample2 do def is_binary_cond do v = "bc" cond do is_binary(v) -> :bin true -> :ok end end end """ end) =~ "nofile:6: warning: this clause cannot match because a previous clause at line 5 always matches" after purge [Sample1, Sample2] end test :empty_clause do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do def hello end """ end) =~ "warning: bodyless clause provided for nonexistent def hello/0" after purge Sample1 end test :used_import_via_alias do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do import List, only: [flatten: 1] defmacro generate do List.duplicate(quote(do: flatten([1, 2, 3])), 100) end end defmodule Sample2 do import Sample1 generate end """ end) == "" after purge [Sample1, Sample2] end test :clause_not_match do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def hello, do: nil def hello, do: nil end """ end) =~ "warning: this clause cannot match because a previous clause at line 2 always matches" after purge Sample end test :clause_with_defaults_should_be_first do assert capture_err(fn -> Code.eval_string ~S""" defmodule Sample do def hello(arg), do: nil def hello(arg \\ 0), do: nil end """ end) =~ "warning: clause with defaults should be the first clause in def hello/1" after purge Sample end test :unused_with_local_with_overridable do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def hello, do: world defp world, do: :ok defoverridable [hello: 0] def hello, do: :ok end """ end) =~ "warning: function world/0 is unused" after purge Sample end test :used_with_local_with_reattached_overridable do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def hello, do: world defp world, do: :ok defoverridable [hello: 0, world: 0] end """ end) == "" after purge Sample end test :undefined_module_attribute do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @foo end """ end) =~ "warning: undefined module attribute @foo, please remove access to @foo or explicitly set it before access" after purge Sample end test :undefined_module_attribute_in_function do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def hello do @foo end end """ end) =~ "warning: undefined module attribute @foo, please remove access to @foo or explicitly set it before access" after purge Sample end test :undefined_module_attribute_with_file do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @foo end """ end) =~ "warning: undefined module attribute @foo, please remove access to @foo or explicitly set it before access" after purge Sample end test :in_guard_empty_list do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def a(x) when x in [], do: x end """ end) =~ "nofile:2: warning: this check/guard will always yield the same result" after purge Sample end test :no_effect_operator do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def a(x) do x != :foo :ok end end """ end) =~ "warning: use of operator != has no effect" after purge Sample end test :badarg_warning do assert capture_err(fn -> assert_raise ArgumentError, fn -> Code.eval_string """ defmodule Sample do Atom.to_string "abc" end """ end end) =~ "warning: this expression will fail with ArgumentError" after purge [Sample] end test :undefined_function_for_behaviour do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do use Behaviour defcallback foo end defmodule Sample2 do @behaviour Sample1 end """ end) =~ "warning: undefined behaviour function foo/0 (for behaviour Sample1)" after purge [Sample1, Sample2, Sample3] end test :undefined_macro_for_behaviour do assert capture_err(fn -> Code.eval_string """ defmodule Sample1 do use Behaviour defmacrocallback foo end defmodule Sample2 do @behaviour Sample1 end """ end) =~ "warning: undefined behaviour macro foo/0 (for behaviour Sample1)" after purge [Sample1, Sample2, Sample3] end test :undefined_behavior do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @behavior Hello end """ end) =~ "warning: @behavior attribute is not supported, please use @behaviour instead" after purge Sample end test :undefined_macro_for_protocol do assert capture_err(fn -> Code.eval_string """ defprotocol Sample1 do def foo(subject) end defimpl Sample1, for: Atom do end """ end) =~ "warning: undefined protocol function foo/1 (for protocol Sample1)" after purge [Sample1, Sample1.Atom] end test :overidden_def do assert capture_err(fn -> Code.eval_string """ defmodule Sample do def foo(x, 1), do: x + 1 def bar(), do: nil def foo(x, 2), do: x * 2 end """ end) =~ "nofile:4: warning: clauses for the same def should be grouped together, def foo/2 was previously defined (nofile:2)" after purge Sample end test :warning_with_overridden_file do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @file "sample" def foo(x), do: :ok end """ end) =~ "sample:3: warning: variable x is unused" after purge Sample end test :warning_on_codepoint_escape do assert capture_err(fn -> Code.eval_string "? " end) =~ "nofile:1: warning: found ? followed by codepoint 0x20 (space), please use \\s instead" end test :typedoc_on_typep do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @typedoc "Something" @typep priv :: any @spec foo() :: priv def foo(), do: nil end """ end) =~ "nofile:3: warning: type priv/0 is private, @typedoc's are always discarded for private types" after purge Sample end test :typedoc_with_no_type do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @typedoc "Something" end """ end) =~ "nofile:1: warning: @typedoc provided but no type follows it" after purge Sample end test :doc_with_no_function do assert capture_err(fn -> Code.eval_string """ defmodule Sample do @doc "Something" end """ end) =~ "nofile:1: warning: @doc provided but no definition follows it" after purge Sample end defp purge(list) when is_list(list) do Enum.each list, &purge/1 end defp purge(module) when is_atom(module) do :code.delete module :code.purge module end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/kernel_test.exs000066400000000000000000000321751254730255300245020ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule KernelTest do use ExUnit.Case, async: true test "=~/2" do assert ("abcd" =~ ~r/c(d)/) == true assert ("abcd" =~ ~r/e/) == false assert ("abcd" =~ ~R/c(d)/) == true assert ("abcd" =~ ~R/e/) == false string = "^ab+cd*$" assert (string =~ "ab+") == true assert (string =~ "bb") == false assert ("abcd" =~ ~r//) == true assert ("abcd" =~ ~R//) == true assert ("abcd" =~ "") == true assert ("" =~ ~r//) == true assert ("" =~ ~R//) == true assert ("" =~ "") == true assert ("" =~ "abcd") == false assert ("" =~ ~r/abcd/) == false assert ("" =~ ~R/abcd/) == false assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> 1234 =~ "hello" end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> 1234 =~ ~r"hello" end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> 1234 =~ ~R"hello" end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> ~r"hello" =~ "hello" end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> ~r"hello" =~ ~r"hello" end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> :abcd =~ ~r// end assert_raise FunctionClauseError, "no function clause matching in Kernel.=~/2", fn -> :abcd =~ "" end assert_raise FunctionClauseError, "no function clause matching in Regex.match?/2", fn -> "abcd" =~ nil end assert_raise FunctionClauseError, "no function clause matching in Regex.match?/2", fn -> "abcd" =~ :abcd end end test "^" do x = List.first([1]) assert_raise MatchError, fn -> {x, ^x} = {2, 2} x end end test "match?/2" do assert match?(_, List.first(1)) == true assert binding() == [] a = List.first([0]) assert match?(b when b > a, 1) == true assert binding() == [a: 0] assert match?(b when b > a, -1) == false assert binding() == [a: 0] end test "in/2" do assert 2 in [1, 2, 3] assert 2 in 1..3 refute 4 in [1, 2, 3] refute 4 in 1..3 list = [1, 2, 3] assert 2 in list refute 4 in list end @at_list [4, 5] @at_range 6..8 def fun_in(x) when x in [0], do: :list def fun_in(x) when x in 1..3, do: :range def fun_in(x) when x in @at_list, do: :at_list def fun_in(x) when x in @at_range, do: :at_range test "in/2 in function guard" do assert fun_in(0) == :list assert fun_in(2) == :range assert fun_in(5) == :at_list assert fun_in(8) == :at_range end defmacrop case_in(x, y) do quote do case 0 do _ when unquote(x) in unquote(y) -> true _ -> false end end end test "in/2 in case guard" do assert case_in(1, [1, 2, 3]) == true assert case_in(1, 1..3) == true assert case_in(2, 1..3) == true assert case_in(3, 1..3) == true assert case_in(-3, -1..-3) == true end test "in/2 in module body" do defmodule In do @foo [:a, :b] true = :a in @foo end end @bitstring <<"foo", 16::4>> test "bitstring attribute" do assert @bitstring == <<"foo", 16::4>> end test "paren as nil" do assert is_nil(()) == true assert ((); ();) == nil assert [ 1, (), 3 ] == [1, nil, 3 ] assert [do: ()] == [do: nil] assert {1, (), 3} == {1, nil, 3} assert (Kernel.&& nil, ()) == nil assert (Kernel.&& nil, ()) == nil assert (() && ()) == nil assert (if(() && ()) do :ok else :error end) == :error end test "__info__(:macros)" do assert {:in, 2} in Kernel.__info__(:macros) end test "__info__(:functions)" do assert not ({:__info__, 1} in Kernel.__info__(:functions)) end def exported?, do: not_exported? defp not_exported?, do: true test "function_exported?/3" do assert function_exported?(__MODULE__, :exported?, 0) refute function_exported?(__MODULE__, :not_exported?, 0) end test "macro_exported?/3" do assert macro_exported?(Kernel, :in, 2) == true assert macro_exported?(Kernel, :def, 1) == true assert macro_exported?(Kernel, :def, 2) == true assert macro_exported?(Kernel, :def, 3) == false assert macro_exported?(Kernel, :no_such_macro, 2) == false end test "apply/3 and apply/2" do assert apply(Enum, :reverse, [[1|[2, 3]]]) == [3, 2, 1] assert apply(fn x -> x * 2 end, [2]) == 4 end test "binding/0 and binding/1" do x = 1 assert binding() == [x: 1] x = 2 assert binding() == [x: 2] y = 3 assert binding() == [x: 2, y: 3] var!(x, :foo) = 4 assert binding() == [x: 2, y: 3] assert binding(:foo) == [x: 4] end defmodule User do assert is_map defstruct name: "john" end defmodule UserTuple do def __struct__({ UserTuple, :ok }) do %User{} end end test "struct/1 and struct/2" do assert struct(User) == %User{name: "john"} user = struct(User, name: "meg") assert user == %User{name: "meg"} assert struct(user, unknown: "key") == user assert struct(user, %{name: "john"}) == %User{name: "john"} assert struct(user, name: "other", __struct__: Post) == %User{name: "other"} user_tuple = {UserTuple, :ok} assert struct(user_tuple, name: "meg") == %User{name: "meg"} end defdelegate my_flatten(list), to: List, as: :flatten defdelegate [map(callback, list)], to: :lists, append_first: true dynamic = :dynamic_flatten defdelegate unquote(dynamic)(list), to: List, as: :flatten test "defdelegate/2" do assert my_flatten([[1]]) == [1] end test "defdelegate/2 with :append_first" do assert map([1], fn(x) -> x + 1 end) == [2] end test "defdelegate/2 with unquote" do assert dynamic_flatten([[1]]) == [1] end test "get_in/2" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert get_in(users, ["john", :age]) == 27 assert get_in(users, ["dave", :age]) == nil assert get_in(nil, ["john", :age]) == nil map = %{"fruits" => ["banana", "apple", "orange"]} assert get_in(map, ["fruits", by_index(0)]) == "banana" assert get_in(map, ["fruits", by_index(3)]) == nil assert get_in(map, ["unknown", by_index(3)]) == :oops assert_raise FunctionClauseError, fn -> get_in(users, []) end end test "put_in/3" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert put_in(users, ["john", :age], 28) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert_raise FunctionClauseError, fn -> put_in(users, [], %{}) end assert_raise ArgumentError, "could not put/update key \"john\" on a nil value", fn -> put_in(nil, ["john", :age], 28) end end test "put_in/2" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert put_in(users["john"][:age], 28) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert put_in(users["john"].age, 28) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert_raise ArgumentError, "could not put/update key :age. Expected map/struct, got: nil", fn -> put_in(users["dave"].age, 19) end assert_raise KeyError, fn -> put_in(users["meg"].unknown, "value") end end test "update_in/3" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert update_in(users, ["john", :age], &(&1 + 1)) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert_raise FunctionClauseError, fn -> update_in(users, [], fn _ -> %{} end) end assert_raise ArgumentError, "could not put/update key \"john\" on a nil value", fn -> update_in(nil, ["john", :age], fn _ -> %{} end) end end test "update_in/2" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert update_in(users["john"][:age], &(&1 + 1)) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert update_in(users["john"].age, &(&1 + 1)) == %{"john" => %{age: 28}, "meg" => %{age: 23}} assert_raise ArgumentError, "could not put/update key :age. Expected map/struct, got: nil", fn -> update_in(users["dave"].age, &(&1 + 1)) end assert_raise KeyError, fn -> put_in(users["meg"].unknown, &(&1 + 1)) end end test "get_and_update_in/3" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert get_and_update_in(users, ["john", :age], &{&1, &1 + 1}) == {27, %{"john" => %{age: 28}, "meg" => %{age: 23}}} map = %{"fruits" => ["banana", "apple", "orange"]} assert get_and_update_in(map, ["fruits", by_index(0)], &{&1, String.reverse(&1)}) == {"banana", %{"fruits" => ["ananab", "apple", "orange"]}} assert get_and_update_in(map, ["fruits", by_index(3)], &{&1, &1}) == {nil, %{"fruits" => ["banana", "apple", "orange"]}} assert get_and_update_in(map, ["unknown", by_index(3)], &{&1, []}) == {:oops, %{"fruits" => ["banana", "apple", "orange"], "unknown" => []}} assert_raise FunctionClauseError, fn -> update_in(users, [], fn _ -> %{} end) end end test "get_and_update_in/2" do users = %{"john" => %{age: 27}, "meg" => %{age: 23}} assert get_and_update_in(users["john"].age, &{&1, &1 + 1}) == {27, %{"john" => %{age: 28}, "meg" => %{age: 23}}} assert_raise ArgumentError, "could not put/update key \"john\" on a nil value", fn -> get_and_update_in(nil["john"][:age], fn nil -> {:ok, 28} end) end assert_raise ArgumentError, "could not put/update key :age. Expected map/struct, got: nil", fn -> get_and_update_in(users["dave"].age, &{&1, &1 + 1}) end assert_raise KeyError, fn -> get_and_update_in(users["meg"].unknown, &{&1, &1 + 1}) end end test "paths" do map = empty_map() assert put_in(map[:foo], "bar") == %{foo: "bar"} assert put_in(empty_map()[:foo], "bar") == %{foo: "bar"} assert put_in(KernelTest.empty_map()[:foo], "bar") == %{foo: "bar"} assert put_in(__MODULE__.empty_map()[:foo], "bar") == %{foo: "bar"} assert_raise ArgumentError, ~r"access at least one element,", fn -> Code.eval_quoted(quote(do: put_in(map, "bar")), []) end assert_raise ArgumentError, ~r"must start with a variable, local or remote call", fn -> Code.eval_quoted(quote(do: put_in(map.foo(1, 2)[:bar], "baz")), []) end end def empty_map, do: %{} def by_index(index) do fn _, nil, next -> next.(:oops) :get, data, next -> next.(Enum.at(data, index)) :get_and_update, data, next -> {get, update} = next.(Enum.at(data, index)) {get, List.replace_at(data, index, update)} end end defmodule PipelineOp do use ExUnit.Case, async: true test "simple" do assert [1, [2], 3] |> List.flatten == [1, 2, 3] end test "nested pipelines" do assert [1, [2], 3] |> List.flatten |> Enum.map(&(&1 * 2)) == [2, 4, 6] end test "local call" do assert [1, [2], 3] |> List.flatten |> local == [2, 4, 6] end test "pipeline with capture" do assert Enum.map([1, 2, 3], &(&1 |> twice |> twice)) == [4, 8, 12] end test "anonymous functions" do assert 1 |> (&(&1*2)).() == 2 assert [1] |> (&hd(&1)).() == 1 end defp twice(a), do: a * 2 defp local(list) do Enum.map(list, &(&1 * 2)) end end defmodule IfScope do use ExUnit.Case, async: true test "variables on nested if" do if true do a = 1 if true do b = 2 end end assert a == 1 assert b == 2 end test "variables on sibling if" do if true do a = 1 if true do b = 2 end if true do c = 3 end end assert a == 1 assert b == 2 assert c == 3 end test "variables counter on nested ifs" do r = (fn() -> 3 end).() # supresses warning at (if r < 0...) r = r - 1 r = r - 1 r = r - 1 if true do r = r - 1 if r < 0, do: r = 0 end assert r == 0 end end defmodule Destructure do use ExUnit.Case, async: true test "less args" do destructure [x, y, z], [1, 2, 3, 4, 5] assert x == 1 assert y == 2 assert z == 3 end test "more args" do destructure [a, b, c, d, e], [1, 2, 3] assert a == 1 assert b == 2 assert c == 3 assert d == nil assert e == nil end test "equal args" do destructure [a, b, c], [1, 2, 3] assert a == 1 assert b == 2 assert c == 3 end test "no values" do destructure [a, b, c], [] assert a == nil assert b == nil assert c == nil end test "works as match" do destructure [1, b, _], [1, 2, 3] assert b == 2 end test "nil values" do destructure [a, b, c], a_nil assert a == nil assert b == nil assert c == nil end test "invalid match" do a = List.first([3]) assert_raise MatchError, fn -> destructure [^a, _b, _c], a_list end end defp a_list, do: [1, 2, 3] defp a_nil, do: nil end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/keyword_test.exs000066400000000000000000000212511254730255300246770ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule KeywordTest do use ExUnit.Case, async: true test "has a literal syntax" do assert [B: 1] == [{:B, 1}] assert [foo?: :bar] == [{:foo?, :bar}] assert [||: 2, +: 1] == [{:||, 2}, {:+, 1}] assert [1, 2, three: :four] == [1, 2, {:three, :four}] end test "is a :: operator on ambiguity" do assert [{:::, _, [{:a, _, _}, {:b, _, _}]}] = quote(do: [a::b]) end test "supports optional comma" do [a: 1, b: 2, c: 3, ] end test "keyword?/1" do assert Keyword.keyword?([]) assert Keyword.keyword?([a: 1]) assert Keyword.keyword?([{Foo, 1}]) refute Keyword.keyword?([{}]) refute Keyword.keyword?(<<>>) end test "new/0" do assert Keyword.new == [] end test "new/1" do assert Keyword.new([{:second_key, 2}, {:first_key, 1}]) == [first_key: 1, second_key: 2] end test "new/2" do assert Keyword.new([:a, :b], fn x -> {x, x} end) == [b: :b, a: :a] end test "get/2 and get/3" do assert Keyword.get(create_keywords, :first_key) == 1 assert Keyword.get(create_keywords, :second_key) == 2 assert Keyword.get(create_keywords, :other_key) == nil assert Keyword.get(create_empty_keywords, :first_key, "default") == "default" end test "get_lazy/3" do Process.put(:get_lazy, 42) fun = fn -> Process.put(:get_lazy, Process.get(:get_lazy) + 1) Process.get(:get_lazy) end assert Keyword.get_lazy(create_keywords, :other_key, fun) == 43 assert Keyword.get_lazy(create_keywords, :other_key, fun) == 44 end test "get_and_update/3" do {get, new_keywords} = Keyword.get_and_update(create_keywords, :first_key, &{&1, "foo"}) assert get == 1 assert new_keywords == [first_key: "foo", second_key: 2] {get, new_keywords} = Keyword.get_and_update(create_keywords, :non_key, &{&1, "foo"}) assert get == nil assert new_keywords == [non_key: "foo", first_key: 1, second_key: 2] end test "fetch!/2" do assert Keyword.fetch!(create_keywords, :first_key) == 1 error = assert_raise KeyError, fn -> Keyword.fetch!(create_keywords, :unknown) end assert error.key == :unknown end test "keys/1" do assert Keyword.keys(create_keywords) == [:first_key, :second_key] assert Keyword.keys(create_empty_keywords) == [] assert_raise FunctionClauseError, fn -> Keyword.keys([:foo]) end end test "values/1" do assert Keyword.values(create_keywords) == [1, 2] assert Keyword.values(create_empty_keywords) == [] assert_raise FunctionClauseError, fn -> Keyword.values([:foo]) end end test "delete/2" do assert Keyword.delete(create_keywords, :second_key) == [first_key: 1] assert Keyword.delete(create_keywords, :other_key) == [first_key: 1, second_key: 2] assert Keyword.delete(create_empty_keywords, :other_key) == [] assert_raise FunctionClauseError, fn -> Keyword.delete([:foo], :foo) end end test "delete/3" do keywords = [a: 1, b: 2, c: 3, a: 2] assert Keyword.delete(keywords, :a, 2) == [a: 1, b: 2, c: 3] assert Keyword.delete(keywords, :a, 1) == [b: 2, c: 3, a: 2] assert_raise FunctionClauseError, fn -> Keyword.delete([:foo], :foo, 0) end end test "put/3" do assert Keyword.put(create_empty_keywords, :first_key, 1) == [first_key: 1] assert Keyword.put(create_keywords, :first_key, 3) == [first_key: 3, second_key: 2] end test "put_new/3" do assert Keyword.put_new(create_empty_keywords, :first_key, 1) == [first_key: 1] assert Keyword.put_new(create_keywords, :first_key, 3) == [first_key: 1, second_key: 2] end test "put_new_lazy/3" do Process.put(:put_new_lazy, 42) fun = fn -> Process.put(:put_new_lazy, Process.get(:put_new_lazy) + 1) Process.get(:put_new_lazy) end assert Keyword.put_new_lazy(create_empty_keywords, :first_key, fun) == [first_key: 43] assert Keyword.put_new_lazy(create_keywords, :first_key, fun) == [first_key: 1, second_key: 2] end test "merge/2" do assert Keyword.merge(create_empty_keywords, create_keywords) == [first_key: 1, second_key: 2] assert Keyword.merge(create_keywords, create_empty_keywords) == [first_key: 1, second_key: 2] assert Keyword.merge(create_keywords, create_keywords) == [first_key: 1, second_key: 2] assert Keyword.merge(create_empty_keywords, create_empty_keywords) == [] assert_raise FunctionClauseError, fn -> Keyword.delete([:foo], [:foo]) end end test "merge/3" do result = Keyword.merge [a: 1, b: 2], [a: 3, d: 4], fn _k, v1, v2 -> v1 + v2 end assert result == [a: 4, b: 2, d: 4] end test "has_key?/2" do assert Keyword.has_key?([a: 1], :a) == true assert Keyword.has_key?([a: 1], :b) == false end test "update!/3" do kw = [a: 1, b: 2, a: 3] assert Keyword.update!(kw, :a, &(&1 * 2)) == [a: 2, b: 2] assert_raise KeyError, fn -> Keyword.update!([a: 1], :b, &(&1 * 2)) end end test "update/4" do kw = [a: 1, b: 2, a: 3] assert Keyword.update(kw, :a, 13, &(&1 * 2)) == [a: 2, b: 2] assert Keyword.update([a: 1], :b, 11, &(&1 * 2)) == [a: 1, b: 11] end defp create_empty_keywords, do: [] defp create_keywords, do: [first_key: 1, second_key: 2] end defmodule Keyword.DuplicatedTest do use ExUnit.Case, async: true test "get/2" do assert Keyword.get(create_keywords, :first_key) == 1 assert Keyword.get(create_keywords, :second_key) == 2 assert Keyword.get(create_keywords, :other_key) == nil assert Keyword.get(create_empty_keywords, :first_key, "default") == "default" end test "get_values/2" do assert Keyword.get_values(create_keywords, :first_key) == [1, 2] assert Keyword.get_values(create_keywords, :second_key) == [2] assert Keyword.get_values(create_keywords, :other_key) == [] assert_raise FunctionClauseError, fn -> Keyword.get_values([:foo], :foo) end end test "keys/1" do assert Keyword.keys(create_keywords) == [:first_key, :first_key, :second_key] assert Keyword.keys(create_empty_keywords) == [] end test "equal?/2" do assert Keyword.equal? [a: 1, b: 2], [b: 2, a: 1] refute Keyword.equal? [a: 1, b: 2], [b: 2, c: 3] end test "values/1" do assert Keyword.values(create_keywords) == [1, 2, 2] assert Keyword.values(create_empty_keywords) == [] end test "delete/2" do assert Keyword.delete(create_keywords, :first_key) == [second_key: 2] assert Keyword.delete(create_keywords, :other_key) == create_keywords assert Keyword.delete(create_empty_keywords, :other_key) == [] end test "delete_first/2" do assert Keyword.delete_first(create_keywords, :first_key) == [first_key: 2, second_key: 2] assert Keyword.delete_first(create_keywords, :other_key) == [first_key: 1, first_key: 2, second_key: 2] assert Keyword.delete_first(create_empty_keywords, :other_key) == [] end test "put/3" do assert Keyword.put(create_empty_keywords, :first_key, 1) == [first_key: 1] assert Keyword.put(create_keywords, :first_key, 1) == [first_key: 1, second_key: 2] end test "merge/2" do assert Keyword.merge(create_empty_keywords, create_keywords) == create_keywords assert Keyword.merge(create_keywords, create_empty_keywords) == create_keywords assert Keyword.merge(create_keywords, create_keywords) == create_keywords assert Keyword.merge(create_empty_keywords, create_empty_keywords) == [] assert Keyword.merge(create_keywords, [first_key: 0]) == [first_key: 0, second_key: 2] assert Keyword.merge(create_keywords, [first_key: 0, first_key: 3]) == [first_key: 0, first_key: 3, second_key: 2] end test "merge/3" do result = Keyword.merge [a: 1, b: 2], [a: 3, d: 4], fn _k, v1, v2 -> v1 + v2 end assert Keyword.equal?(result, [a: 4, b: 2, d: 4]) end test "has_key?/2" do assert Keyword.has_key?([a: 1], :a) == true assert Keyword.has_key?([a: 1], :b) == false end test "take/2" do assert Keyword.take([], []) == [] assert Keyword.take([a: 0, b: 1, a: 2], []) == [] assert Keyword.take([a: 0, b: 1, a: 2], [:a]) == [a: 0, a: 2] assert Keyword.take([a: 0, b: 1, a: 2], [:b]) == [b: 1] assert_raise FunctionClauseError, fn -> Keyword.take([:foo], [:foo]) end end test "drop/2" do assert Keyword.drop([], []) == [] assert Keyword.drop([a: 0, b: 1, a: 2], []) == [a: 0, b: 1, a: 2] assert Keyword.drop([a: 0, b: 1, a: 2], [:a]) == [b: 1] assert Keyword.drop([a: 0, b: 1, a: 2], [:b]) == [a: 0, a: 2] assert_raise FunctionClauseError, fn -> Keyword.drop([:foo], [:foo]) end end defp create_empty_keywords, do: [] defp create_keywords, do: [first_key: 1, first_key: 2, second_key: 2] end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/list/000077500000000000000000000000001254730255300224055ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/list/chars_test.exs000066400000000000000000000012221254730255300252620ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule List.Chars.AtomTest do use ExUnit.Case, async: true test :basic do assert to_char_list(:foo) == 'foo' end end defmodule List.Chars.BitStringTest do use ExUnit.Case, async: true test :basic do assert to_char_list("foo") == 'foo' end end defmodule List.Chars.NumberTest do use ExUnit.Case, async: true test :integer do assert to_char_list(1) == '1' end test :float do assert to_char_list(1.0) == '1.0' end end defmodule List.Chars.ListTest do use ExUnit.Case, async: true test :basic do assert to_char_list([ 1, "b", 3 ]) == [1, "b", 3] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/list_test.exs000066400000000000000000000120471254730255300241710ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ListTest do use ExUnit.Case, async: true test :cons_cell_precedence do assert [1|:lists.flatten([2, 3])] == [1, 2, 3] end test :optional_comma do assert [1] == [ 1, ] assert [1, 2, 3] == [1, 2, 3, ] end test :partial_application do assert (&[&1, 2]).(1) == [1, 2] assert (&[&1, &2]).(1, 2) == [1, 2] assert (&[&2, &1]).(2, 1) == [1, 2] assert (&[&1|&2]).(1, 2) == [1|2] assert (&[&1, &2|&3]).(1, 2, 3) == [1, 2|3] end test :wrap do assert List.wrap([1, 2, 3]) == [1, 2, 3] assert List.wrap(1) == [1] assert List.wrap(nil) == [] end test :flatten do assert List.flatten([1, 2, 3]) == [1, 2, 3] assert List.flatten([1, [2], 3]) == [1, 2, 3] assert List.flatten([[1, [2], 3]]) == [1, 2, 3] assert List.flatten([]) == [] assert List.flatten([[]]) == [] end test :flatten_with_tail do assert List.flatten([1, 2, 3], [4, 5]) == [1, 2, 3, 4, 5] assert List.flatten([1, [2], 3], [4, 5]) == [1, 2, 3, 4, 5] assert List.flatten([[1, [2], 3]], [4, 5]) == [1, 2, 3, 4, 5] end test :foldl do assert List.foldl([1, 2, 3], 0, fn x, y -> x + y end) == 6 assert List.foldl([1, 2, 3], 10, fn x, y -> x + y end) == 16 assert List.foldl([1, 2, 3, 4], 0, fn x, y -> x - y end) == 2 end test :foldr do assert List.foldr([1, 2, 3], 0, fn x, y -> x + y end) == 6 assert List.foldr([1, 2, 3], 10, fn x, y -> x + y end) == 16 assert List.foldr([1, 2, 3, 4], 0, fn x, y -> x - y end) == -2 end test :reverse do assert Enum.reverse([1, 2, 3]) == [3, 2, 1] end test :duplicate do assert List.duplicate(1, 3) == [1, 1, 1] assert List.duplicate([1], 1) == [[1]] end test :last do assert List.last([]) == nil assert List.last([1]) == 1 assert List.last([1, 2, 3]) == 3 end test :zip do assert List.zip([[1, 4], [2, 5], [3, 6]]) == [{1, 2, 3}, {4, 5, 6}] assert List.zip([[1, 4], [2, 5, 0], [3, 6]]) == [{1, 2, 3}, {4, 5, 6}] assert List.zip([[1], [2, 5], [3, 6]]) == [{1, 2, 3}] assert List.zip([[1, 4], [2, 5], []]) == [] end test :keyfind do assert List.keyfind([a: 1, b: 2], :a, 0) == {:a, 1} assert List.keyfind([a: 1, b: 2], 2, 1) == {:b, 2} assert List.keyfind([a: 1, b: 2], :c, 0) == nil end test :keyreplace do assert List.keyreplace([a: 1, b: 2], :a, 0, {:a, 3}) == [a: 3, b: 2] assert List.keyreplace([a: 1], :b, 0, {:b, 2}) == [a: 1] end test :keysort do assert List.keysort([a: 4, b: 3, c: 5], 1) == [b: 3, a: 4, c: 5] assert List.keysort([a: 4, c: 1, b: 2], 0) == [a: 4, b: 2, c: 1] end test :keystore do assert List.keystore([a: 1, b: 2], :a, 0, {:a, 3}) == [a: 3, b: 2] assert List.keystore([a: 1], :b, 0, {:b, 2}) == [a: 1, b: 2] end test :keymember? do assert List.keymember?([a: 1, b: 2], :a, 0) == true assert List.keymember?([a: 1, b: 2], 2, 1) == true assert List.keymember?([a: 1, b: 2], :c, 0) == false end test :keydelete do assert List.keydelete([a: 1, b: 2], :a, 0) == [{:b, 2}] assert List.keydelete([a: 1, b: 2], 2, 1) == [{:a, 1}] assert List.keydelete([a: 1, b: 2], :c, 0) == [{:a, 1}, {:b, 2}] end test :insert_at do assert List.insert_at([1, 2, 3], 0, 0) == [0, 1, 2, 3] assert List.insert_at([1, 2, 3], 3, 0) == [1, 2, 3, 0] assert List.insert_at([1, 2, 3], 2, 0) == [1, 2, 0, 3] assert List.insert_at([1, 2, 3], 10, 0) == [1, 2, 3, 0] assert List.insert_at([1, 2, 3], -1, 0) == [1, 2, 3, 0] assert List.insert_at([1, 2, 3], -4, 0) == [0, 1, 2, 3] assert List.insert_at([1, 2, 3], -10, 0) == [0, 1, 2, 3] end test :replace_at do assert List.replace_at([1, 2, 3], 0, 0) == [0, 2, 3] assert List.replace_at([1, 2, 3], 1, 0) == [1, 0, 3] assert List.replace_at([1, 2, 3], 2, 0) == [1, 2, 0] assert List.replace_at([1, 2, 3], 3, 0) == [1, 2, 3] assert List.replace_at([1, 2, 3], -1, 0) == [1, 2, 0] assert List.replace_at([1, 2, 3], -4, 0) == [1, 2, 3] end test :update_at do assert List.update_at([1, 2, 3], 0, &(&1 + 1)) == [2, 2, 3] assert List.update_at([1, 2, 3], 1, &(&1 + 1)) == [1, 3, 3] assert List.update_at([1, 2, 3], 2, &(&1 + 1)) == [1, 2, 4] assert List.update_at([1, 2, 3], 3, &(&1 + 1)) == [1, 2, 3] assert List.update_at([1, 2, 3], -1, &(&1 + 1)) == [1, 2, 4] assert List.update_at([1, 2, 3], -4, &(&1 + 1)) == [1, 2, 3] end test :delete_at do Enum.each [-1, 0, 1], fn i -> assert [] = List.delete_at([], i) end assert List.delete_at([1, 2, 3], 0) == [2, 3] assert List.delete_at([1, 2, 3], 2) == [1, 2] assert List.delete_at([1, 2, 3], 3) == [1, 2, 3] assert List.delete_at([1, 2, 3], -1) == [1, 2] assert List.delete_at([1, 2, 3], -3) == [2, 3] assert List.delete_at([1, 2, 3], -4) == [1, 2, 3] end test :to_string do assert List.to_string([?æ, ?ß]) == "æß" assert List.to_string([?a, ?b, ?c]) == "abc" assert_raise UnicodeConversionError, "invalid code point 57343", fn -> List.to_string([0xDFFF]) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/macro_test.exs000066400000000000000000000443341254730255300243230ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule Macro.ExternalTest do defmacro external do line = 18 file = __ENV__.file ^line = __CALLER__.line ^file = __CALLER__.file ^line = Macro.Env.location(__CALLER__)[:line] ^file = Macro.Env.location(__CALLER__)[:file] end defmacro oror(left, right) do quote do: unquote(left) || unquote(right) end end defmodule MacroTest do use ExUnit.Case, async: true # Changing the lines above will make compilation # fail since we are asserting on the caller lines import Macro.ExternalTest ## Escape test :escape_handle_tuples_with_size_different_than_two do assert {:{}, [], [:a]} == Macro.escape({:a}) assert {:{}, [], [:a, :b, :c]} == Macro.escape({:a, :b, :c}) assert {:{}, [], [:a, {:{}, [], [1, 2, 3]}, :c]} == Macro.escape({:a, {1, 2, 3}, :c}) end test :escape_simply_returns_tuples_with_size_equal_to_two do assert {:a, :b} == Macro.escape({:a, :b}) end test :escape_simply_returns_any_other_structure do assert [1, 2, 3] == Macro.escape([1, 2, 3]) end test :escape_handles_maps do assert {:%{}, [], [a: 1]} = Macro.escape(%{a: 1}) end test :escape_handles_bitstring do assert {:<<>>, [], [{:::, [], [1, 4]}, ","]} == Macro.escape(<<300::12>>) end test :escape_works_recursively do assert [1, {:{}, [], [:a, :b, :c]}, 3] == Macro.escape([1, {:a, :b, :c}, 3]) end test :escape_improper do assert [{:|, [], [1, 2]}] == Macro.escape([1|2]) assert [1, {:|, [], [2, 3]}] == Macro.escape([1, 2|3]) end test :escape_with_unquote do contents = quote unquote: false, do: unquote(1) assert Macro.escape(contents, unquote: true) == 1 contents = quote unquote: false, do: unquote(x) assert Macro.escape(contents, unquote: true) == {:x, [], MacroTest} end defp eval_escaped(contents) do {eval, []} = Code.eval_quoted(Macro.escape(contents, unquote: true)) eval end test :escape_with_remote_unquote do contents = quote unquote: false, do: Kernel.unquote(:is_atom)(:ok) assert eval_escaped(contents) == quote(do: Kernel.is_atom(:ok)) end test :escape_with_nested_unquote do contents = quote do quote do: unquote(x) end assert eval_escaped(contents) == quote do: (quote do: unquote(x)) end test :escape_with_alias_or_no_args_remote_unquote do contents = quote unquote: false, do: Kernel.unquote(:self) assert eval_escaped(contents) == quote(do: Kernel.self()) contents = quote unquote: false, do: x.unquote(Foo) assert eval_escaped(contents) == quote(do: x.unquote(Foo)) end test :escape_with_splicing do contents = quote unquote: false, do: [1, 2, 3, 4, 5] assert Macro.escape(contents, unquote: true) == [1, 2, 3, 4, 5] contents = quote unquote: false, do: [1, 2, unquote_splicing([3, 4, 5])] assert eval_escaped(contents) == [1, 2, 3, 4, 5] contents = quote unquote: false, do: [unquote_splicing([1, 2, 3]), 4, 5] assert eval_escaped(contents) == [1, 2, 3, 4, 5] contents = quote unquote: false, do: [unquote_splicing([1, 2, 3]), unquote_splicing([4, 5])] assert eval_escaped(contents) == [1, 2, 3, 4, 5] contents = quote unquote: false, do: [1, unquote_splicing([2]), 3, unquote_splicing([4]), 5] assert eval_escaped(contents) == [1, 2, 3, 4, 5] contents = quote unquote: false, do: [1, unquote_splicing([2]), 3, unquote_splicing([4])|[5]] assert eval_escaped(contents) == [1, 2, 3, 4, 5] end ## Expansion test :expand_once do assert {:||, _, _} = Macro.expand_once(quote(do: oror(1, false)), __ENV__) end test :expand_once_with_raw_atom do assert Macro.expand_once(quote(do: :foo), __ENV__) == :foo end test :expand_once_with_current_module do assert Macro.expand_once(quote(do: __MODULE__), __ENV__) == __MODULE__ end test :expand_once_with_main do assert Macro.expand_once(quote(do: Elixir), __ENV__) == Elixir end test :expand_once_with_simple_alias do assert Macro.expand_once(quote(do: Foo), __ENV__) == Foo end test :expand_once_with_current_module_plus_alias do assert Macro.expand_once(quote(do: __MODULE__.Foo), __ENV__) == __MODULE__.Foo end test :expand_once_with_main_plus_alias do assert Macro.expand_once(quote(do: Elixir.Foo), __ENV__) == Foo end test :expand_once_with_custom_alias do alias Foo, as: Bar assert Macro.expand_once(quote(do: Bar.Baz), __ENV__) == Foo.Baz end test :expand_once_with_main_plus_custom_alias do alias Foo, as: Bar, warn: false assert Macro.expand_once(quote(do: Elixir.Bar.Baz), __ENV__) == Elixir.Bar.Baz end test :expand_once_with_op do assert Macro.expand_once(quote(do: Foo.bar.Baz), __ENV__) == (quote do Foo.bar.Baz end) end test :expand_once_with_erlang do assert Macro.expand_once(quote(do: :foo), __ENV__) == :foo end test :expand_once_env do env = %{__ENV__ | line: 0} assert Macro.expand_once(quote(do: __ENV__), env) == {:%{}, [], Map.to_list(env)} assert Macro.expand_once(quote(do: __ENV__.file), env) == env.file assert Macro.expand_once(quote(do: __ENV__.unknown), env) == quote(do: __ENV__.unknown) end defmacro local_macro do :local_macro end test :expand_once_local_macro do assert Macro.expand_once(quote(do: local_macro), __ENV__) == :local_macro end test :expand_once_checks_vars do local_macro = 1 assert local_macro == 1 quote = {:local_macro, [], nil} assert Macro.expand_once(quote, __ENV__) == quote end defp expand_once_and_clean(quoted, env) do cleaner = &Keyword.drop(&1, [:counter]) quoted |> Macro.expand_once(env) |> Macro.prewalk(&Macro.update_meta(&1, cleaner)) end test :expand_once_with_imported_macro do temp_var = {:x, [], Kernel} assert expand_once_and_clean(quote(do: 1 || false), __ENV__) == (quote context: Kernel do case 1 do unquote(temp_var) when unquote(temp_var) in [false, nil] -> false unquote(temp_var) -> unquote(temp_var) end end) end test :expand_once_with_require_macro do temp_var = {:x, [], Kernel} assert expand_once_and_clean(quote(do: Kernel.||(1, false)), __ENV__) == (quote context: Kernel do case 1 do unquote(temp_var) when unquote(temp_var) in [false, nil] -> false unquote(temp_var) -> unquote(temp_var) end end) end test :expand_once_with_not_expandable_expression do expr = quote(do: other(1, 2, 3)) assert Macro.expand_once(expr, __ENV__) == expr end @foo 1 @bar Macro.expand_once(quote(do: @foo), __ENV__) test :expand_once_with_module_at do assert @bar == 1 end defp expand_and_clean(quoted, env) do cleaner = &Keyword.drop(&1, [:counter]) quoted |> Macro.expand(env) |> Macro.prewalk(&Macro.update_meta(&1, cleaner)) end test :expand do temp_var = {:x, [], Kernel} assert expand_and_clean(quote(do: oror(1, false)), __ENV__) == (quote context: Kernel do case 1 do unquote(temp_var) when unquote(temp_var) in [false, nil] -> false unquote(temp_var) -> unquote(temp_var) end end) end test :var do assert Macro.var(:foo, nil) == {:foo, [], nil} assert Macro.var(:foo, Other) == {:foo, [], Other} end ## to_string test :var_to_string do assert Macro.to_string(quote do: foo) == "foo" end test :local_call_to_string do assert Macro.to_string(quote do: foo(1, 2, 3)) == "foo(1, 2, 3)" assert Macro.to_string(quote do: foo([1, 2, 3])) == "foo([1, 2, 3])" end test :remote_call_to_string do assert Macro.to_string(quote do: foo.bar(1, 2, 3)) == "foo.bar(1, 2, 3)" assert Macro.to_string(quote do: foo.bar([1, 2, 3])) == "foo.bar([1, 2, 3])" end test :low_atom_remote_call_to_string do assert Macro.to_string(quote do: :foo.bar(1, 2, 3)) == ":foo.bar(1, 2, 3)" end test :big_atom_remote_call_to_string do assert Macro.to_string(quote do: Foo.Bar.bar(1, 2, 3)) == "Foo.Bar.bar(1, 2, 3)" end test :remote_and_fun_call_to_string do assert Macro.to_string(quote do: foo.bar.(1, 2, 3)) == "foo.bar().(1, 2, 3)" assert Macro.to_string(quote do: foo.bar.([1, 2, 3])) == "foo.bar().([1, 2, 3])" end test :atom_call_to_string do assert Macro.to_string(quote do: :foo.(1, 2, 3)) == ":foo.(1, 2, 3)" end test :aliases_call_to_string do assert Macro.to_string(quote do: Foo.Bar.baz(1, 2, 3)) == "Foo.Bar.baz(1, 2, 3)" assert Macro.to_string(quote do: Foo.Bar.baz([1, 2, 3])) == "Foo.Bar.baz([1, 2, 3])" end test :sigil_call_to_string do assert Macro.to_string(quote do: ~r"123") == ~s/~r"123"/ assert Macro.to_string(quote do: ~r"123"u) == ~s/~r"123"u/ assert Macro.to_string(quote do: ~r"\n123") == ~s/~r"\\\\n123"/ assert Macro.to_string(quote do: ~r"1#{two}3") == ~S/~r"1#{two}3"/ assert Macro.to_string(quote do: ~r"1#{two}3"u) == ~S/~r"1#{two}3"u/ assert Macro.to_string(quote do: ~R"123") == ~s/~R"123"/ assert Macro.to_string(quote do: ~R"123"u) == ~s/~R"123"u/ assert Macro.to_string(quote do: ~R"\n123") == ~s/~R"\\\\n123"/ end test :arrow_to_string do assert Macro.to_string(quote do: foo(1, (2 -> 3))) == "foo(1, (2 -> 3))" end test :blocks_to_string do assert Macro.to_string(quote do: (1; 2; (:foo; :bar); 3)) <> "\n" == """ ( 1 2 ( :foo :bar ) 3 ) """ end test :if_else_to_string do assert Macro.to_string(quote do: (if foo, do: bar, else: baz)) <> "\n" == """ if(foo) do bar else baz end """ end test :case_to_string do assert Macro.to_string(quote do: (case foo do true -> 0; false -> (1; 2) end)) <> "\n" == """ case(foo) do true -> 0 false -> 1 2 end """ end test :fn_to_string do assert Macro.to_string(quote do: (fn -> 1 + 2 end)) == "fn -> 1 + 2 end" assert Macro.to_string(quote do: (fn(x) -> x + 1 end)) == "fn x -> x + 1 end" assert Macro.to_string(quote do: (fn(x) -> y = x + 1; y end)) <> "\n" == """ fn x -> y = x + 1 y end """ assert Macro.to_string(quote do: (fn(x) -> y = x + 1; y; (z) -> z end)) <> "\n" == """ fn x -> y = x + 1 y z -> z end """ end test :when do assert Macro.to_string(quote do: (() -> x)) == "(() -> x)" assert Macro.to_string(quote do: (x when y -> z)) == "(x when y -> z)" assert Macro.to_string(quote do: (x, y when z -> w)) == "((x, y) when z -> w)" assert Macro.to_string(quote do: ((x, y) when z -> w)) == "((x, y) when z -> w)" end test :nested_to_string do assert Macro.to_string(quote do: (defmodule Foo do def foo do 1 + 1 end end)) <> "\n" == """ defmodule(Foo) do def(foo) do 1 + 1 end end """ end test :op_precedence_to_string do assert Macro.to_string(quote do: (1 + 2) * (3 - 4)) == "(1 + 2) * (3 - 4)" assert Macro.to_string(quote do: ((1 + 2) * 3) - 4) == "(1 + 2) * 3 - 4" assert Macro.to_string(quote do: (1 + 2 + 3) == "(1 + 2 + 3)") assert Macro.to_string(quote do: (1 + 2 - 3) == "(1 + 2 - 3)") end test :containers_to_string do assert Macro.to_string(quote do: {}) == "{}" assert Macro.to_string(quote do: []) == "[]" assert Macro.to_string(quote do: {1, 2, 3}) == "{1, 2, 3}" assert Macro.to_string(quote do: [ 1, 2, 3 ]) == "[1, 2, 3]" assert Macro.to_string(quote do: %{}) == "%{}" assert Macro.to_string(quote do: %{:foo => :bar}) == "%{foo: :bar}" assert Macro.to_string(quote do: %{{1, 2} => [1, 2, 3]}) == "%{{1, 2} => [1, 2, 3]}" assert Macro.to_string(quote do: %{map | "a" => "b"}) == "%{map | \"a\" => \"b\"}" assert Macro.to_string(quote do: [ 1, 2, 3 ]) == "[1, 2, 3]" assert Macro.to_string(quote do: << 1, 2, 3 >>) == "<<1, 2, 3>>" assert Macro.to_string(quote do: << <<1>> >>) == "<< <<1>> >>" end test :struct_to_string do assert Macro.to_string(quote do: %Test{}) == "%Test{}" assert Macro.to_string(quote do: %Test{foo: 1, bar: 1}) == "%Test{foo: 1, bar: 1}" assert Macro.to_string(quote do: %Test{struct | foo: 2}) == "%Test{struct | foo: 2}" assert Macro.to_string(quote do: %Test{} + 1) == "%Test{} + 1" end test :binary_ops_to_string do assert Macro.to_string(quote do: 1 + 2) == "1 + 2" assert Macro.to_string(quote do: [ 1, 2 | 3 ]) == "[1, 2 | 3]" assert Macro.to_string(quote do: [h|t] = [1, 2, 3]) == "[h | t] = [1, 2, 3]" assert Macro.to_string(quote do: (x ++ y) ++ z) == "(x ++ y) ++ z" end test :unary_ops_to_string do assert Macro.to_string(quote do: not 1) == "not 1" assert Macro.to_string(quote do: not foo) == "not foo" assert Macro.to_string(quote do: -1) == "-1" assert Macro.to_string(quote do: !(foo > bar)) == "!(foo > bar)" assert Macro.to_string(quote do: @foo(bar)) == "@foo(bar)" assert Macro.to_string(quote do: identity(&1)) == "identity(&1)" assert Macro.to_string(quote do: identity(&foo)) == "identity(&foo)" end test :access_to_string do assert Macro.to_string(quote do: a[b]) == "a[b]" assert Macro.to_string(quote do: a[1 + 2]) == "a[1 + 2]" end test :kw_list_to_string do assert Macro.to_string(quote do: [a: a, b: b]) == "[a: a, b: b]" assert Macro.to_string(quote do: [a: 1, b: 1 + 2]) == "[a: 1, b: 1 + 2]" assert Macro.to_string(quote do: ["a.b": 1, c: 1 + 2]) == "[\"a.b\": 1, c: 1 + 2]" end test :interpolation_to_string do assert Macro.to_string(quote do: "foo#{bar}baz") == ~S["foo#{bar}baz"] end test :charlist_to_string do assert Macro.to_string(quote do: []) == "[]" assert Macro.to_string(quote do: 'abc') == "'abc'" end test :last_arg_kw_list_to_string do assert Macro.to_string(quote do: foo([])) == "foo([])" assert Macro.to_string(quote do: foo(x: y)) == "foo(x: y)" assert Macro.to_string(quote do: foo(x: 1 + 2)) == "foo(x: 1 + 2)" assert Macro.to_string(quote do: foo(x: y, p: q)) == "foo(x: y, p: q)" assert Macro.to_string(quote do: foo(a, x: y, p: q)) == "foo(a, x: y, p: q)" assert Macro.to_string(quote do: {[]}) == "{[]}" assert Macro.to_string(quote do: {[a: b]}) == "{[a: b]}" assert Macro.to_string(quote do: {x, a: b}) == "{x, [a: b]}" end test :to_string_with_fun do assert Macro.to_string(quote(do: foo(1, 2, 3)), fn _, string -> ":#{string}:" end) == ":foo(:1:, :2:, :3:):" assert Macro.to_string(quote(do: Bar.foo(1, 2, 3)), fn _, string -> ":#{string}:" end) == "::Bar:.foo(:1:, :2:, :3:):" end ## validate test :validate do ref = make_ref() assert Macro.validate(1) == :ok assert Macro.validate(1.0) == :ok assert Macro.validate(:foo) == :ok assert Macro.validate("bar") == :ok assert Macro.validate(self()) == :ok assert Macro.validate({1, 2}) == :ok assert Macro.validate({:foo, [], :baz}) == :ok assert Macro.validate({:foo, [], []}) == :ok assert Macro.validate([1, 2, 3]) == :ok assert Macro.validate(<<0::4>>) == {:error, <<0::4>>} assert Macro.validate(ref) == {:error, ref} assert Macro.validate({1, ref}) == {:error, ref} assert Macro.validate({ref, 2}) == {:error, ref} assert Macro.validate([1, ref, 3]) == {:error, ref} assert Macro.validate({:foo, [], 0}) == {:error, {:foo, [], 0}} assert Macro.validate({:foo, 0, []}) == {:error, {:foo, 0, []}} end ## decompose_call test :decompose_call do assert Macro.decompose_call(quote do: foo) == {:foo, []} assert Macro.decompose_call(quote do: foo()) == {:foo, []} assert Macro.decompose_call(quote do: foo(1, 2, 3)) == {:foo, [1, 2, 3]} assert Macro.decompose_call(quote do: M.N.foo(1, 2, 3)) == {{:__aliases__, [alias: false], [:M, :N]}, :foo, [1, 2, 3]} assert Macro.decompose_call(quote do: :foo.foo(1, 2, 3)) == {:foo, :foo, [1, 2, 3]} assert Macro.decompose_call(quote do: 1.(1, 2, 3)) == :error assert Macro.decompose_call(quote do: "some string") == :error end ## env test :env_stacktrace do env = %{__ENV__ | file: "foo", line: 12} assert Macro.Env.stacktrace(env) == [{__MODULE__, :"test env_stacktrace", 1, [file: "foo", line: 12]}] env = %{env | function: nil} assert Macro.Env.stacktrace(env) == [{__MODULE__, :__MODULE__, 0, [file: "foo", line: 12]}] env = %{env | module: nil} assert Macro.Env.stacktrace(env) == [{:elixir_compiler, :__FILE__, 1, [file: "foo", line: 12]}] end test :context_modules do defmodule Foo.Bar do assert __MODULE__ in __ENV__.context_modules end end ## pipe/unpipe test :pipe do assert Macro.pipe(1, quote(do: foo), 0) == quote(do: foo(1)) assert Macro.pipe(1, quote(do: foo(2)), 0) == quote(do: foo(1, 2)) assert Macro.pipe(1, quote(do: foo), -1) == quote(do: foo(1)) assert Macro.pipe(2, quote(do: foo(1)), -1) == quote(do: foo(1, 2)) assert_raise ArgumentError, ~r"cannot pipe 1 into 2", fn -> Macro.pipe(1, 2, 0) end end test :unpipe do assert Macro.unpipe(quote(do: foo)) == quote(do: [{foo, 0}]) assert Macro.unpipe(quote(do: foo |> bar)) == quote(do: [{foo, 0}, {bar, 0}]) assert Macro.unpipe(quote(do: foo |> bar |> baz)) == quote(do: [{foo, 0}, {bar, 0}, {baz, 0}]) end ## pre/postwalk test :prewalk do assert prewalk({:foo, [], nil}) == [{:foo, [], nil}] assert prewalk({:foo, [], [1, 2, 3]}) == [{:foo, [], [1, 2, 3]}, 1, 2, 3] assert prewalk({{:., [], [:foo, :bar]}, [], [1, 2, 3]}) == [{{:., [], [:foo, :bar]}, [], [1, 2, 3]}, {:., [], [:foo, :bar]}, :foo, :bar, 1, 2, 3] assert prewalk({[1, 2, 3], [4, 5, 6]}) == [{[1, 2, 3], [4, 5, 6]}, [1, 2, 3], 1, 2, 3, [4, 5, 6], 4, 5, 6] end defp prewalk(ast) do Macro.prewalk(ast, [], &{&1, [&1|&2]}) |> elem(1) |> Enum.reverse end test :postwalk do assert postwalk({:foo, [], nil}) == [{:foo, [], nil}] assert postwalk({:foo, [], [1, 2, 3]}) == [1, 2, 3, {:foo, [], [1, 2, 3]}] assert postwalk({{:., [], [:foo, :bar]}, [], [1, 2, 3]}) == [:foo, :bar, {:., [], [:foo, :bar]}, 1, 2, 3, {{:., [], [:foo, :bar]}, [], [1, 2, 3]}] assert postwalk({[1, 2, 3], [4, 5, 6]}) == [1, 2, 3, [1, 2, 3], 4, 5, 6, [4, 5, 6], {[1, 2, 3], [4, 5, 6]}] end defp postwalk(ast) do Macro.postwalk(ast, [], &{&1, [&1|&2]}) |> elem(1) |> Enum.reverse end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/map_set_test.exs000066400000000000000000000043571254730255300246530ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule MapSetTest do use ExUnit.Case, async: true alias MapSet, as: S test "put" do assert S.equal?(S.put(S.new, 1), make([1])) assert S.equal?(S.put(make([1, 3, 4]), 2), make(1..4)) assert S.equal?(S.put(make(5..100), 10), make(5..100)) end test "union" do assert S.equal?(S.union(make([1, 3, 4]), S.new), make([1, 3, 4])) assert S.equal?(S.union(make(5..15), make(10..25)), make(5..25)) assert S.equal?(S.union(make(1..120), make(1..100)), make(1..120)) end test "intersection" do assert S.equal?(S.intersection(S.new, make(1..21)), S.new) assert S.equal?(S.intersection(make(1..21), make(4..24)), make(4..21)) assert S.equal?(S.intersection(make(2..100), make(1..120)), make(2..100)) end test "difference" do assert S.equal?(S.difference(make(2..20), S.new), make(2..20)) assert S.equal?(S.difference(make(2..20), make(1..21)), S.new) assert S.equal?(S.difference(make(1..101), make(2..100)), make([1, 101])) end test "disjoint?" do assert S.disjoint?(S.new, S.new) assert S.disjoint?(make(1..6), make(8..20)) refute S.disjoint?(make(1..6), make(5..15)) refute S.disjoint?(make(1..120), make(1..6)) end test "subset?" do assert S.subset?(S.new, S.new) assert S.subset?(make(1..6), make(1..10)) assert S.subset?(make(1..6), make(1..120)) refute S.subset?(make(1..120), make(1..6)) end test "equal?" do assert S.equal?(S.new, S.new) refute S.equal?(make(1..20), make(2..21)) assert S.equal?(make(1..120), make(1..120)) end test "delete" do assert S.equal?(S.delete(S.new, 1), S.new) assert S.equal?(S.delete(make(1..4), 5), make(1..4)) assert S.equal?(S.delete(make(1..4), 1), make(2..4)) assert S.equal?(S.delete(make(1..4), 2), make([1, 3, 4])) end test "size" do assert S.size(S.new) == 0 assert S.size(make(5..15)) == 11 assert S.size(make(2..100)) == 99 end test "to_list" do assert S.to_list(S.new) == [] list = S.to_list(make(1..20)) assert Enum.sort(list) == Enum.to_list(1..20) list = S.to_list(make(5..120)) assert Enum.sort(list) == Enum.to_list(5..120) end defp make(collection) do Enum.into(collection, S.new) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/map_test.exs000066400000000000000000000074151254730255300237760ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule MapTest do use ExUnit.Case, async: true defp empty_map do %{} end defp two_items_map do %{a: 1, b: 2} end @map %{a: 1, b: 2} test "maps in attributes" do assert @map == %{a: 1, b: 2} end test "maps when quoted" do assert (quote do %{foo: 1} end) == {:%{}, [], [{:foo, 1}]} assert (quote do % {foo: 1} end) == {:%{}, [], [{:foo, 1}]} end test "structs when quoted" do assert (quote do %User{foo: 1} end) == {:%, [], [ {:__aliases__, [alias: false], [:User]}, {:%{}, [], [{:foo, 1}]} ]} assert (quote do % User{foo: 1} end) == {:%, [], [ {:__aliases__, [alias: false], [:User]}, {:%{}, [], [{:foo, 1}]} ]} assert (quote do %unquote(User){foo: 1} end) == {:%, [], [User, {:%{}, [], [{:foo, 1}]}]} end test "maps keywords and atoms" do assert [%{}: :%] == [{:%{}, :%}] assert [%: :%{}] == [{:%, :%{}}] end test "maps with variables" do a = 0 assert %{a: a = 1, b: a} == %{a: 1, b: 0} assert a == 1 end test "is_map/1" do assert is_map empty_map refute is_map(Enum.to_list(empty_map)) end test "map_size/1" do assert map_size(empty_map) == 0 assert map_size(two_items_map) == 2 end test "maps with optional comma" do assert %{a: :b,} == %{a: :b} assert %{1 => 2,} == %{1 => 2} assert %{1 => 2, a: :b,} == %{1 => 2, a: :b} end test "maps with duplicate keys" do assert %{a: :b, a: :c} == %{a: :c} assert %{1 => 2, 1 => 3} == %{1 => 3} assert %{:a => :b, a: :c} == %{a: :c} end test "update maps" do assert %{two_items_map | a: 3} == %{a: 3, b: 2} # TODO: proper handling of API changes in different Erlang/OTP releases case :erlang.system_info(:otp_release) do '17' -> assert_raise ArgumentError, fn -> %{two_items_map | c: 3} end _ -> assert_raise KeyError, fn -> %{two_items_map | c: 3} end end end test "map access" do assert two_items_map.a == 1 assert_raise KeyError, fn -> two_items_map.c end end defmodule ExternalUser do def __struct__ do %{__struct__: ThisDoesNotLeak, name: "john", age: 27} end end test "structs" do assert %ExternalUser{} == %{__struct__: ExternalUser, name: "john", age: 27} assert %ExternalUser{name: "meg"} == %{__struct__: ExternalUser, name: "meg", age: 27} user = %ExternalUser{} assert %ExternalUser{user | name: "meg"} == %{__struct__: ExternalUser, name: "meg", age: 27} %ExternalUser{name: name} = %ExternalUser{} assert name == "john" map = %{} assert_raise BadStructError, "expected a struct named MapTest.ExternalUser, got: %{}", fn -> %ExternalUser{map | name: "meg"} end end test "map from struct" do assert Map.from_struct(ExternalUser) == %{name: "john", age: 27} assert Map.from_struct(%ExternalUser{name: "meg"}) == %{name: "meg", age: 27} assert_raise FunctionClauseError, fn -> Map.from_struct(%{name: "meg"}) end end defmodule LocalUser do defmodule NestedUser do defstruct [] end defstruct name: "john", nested: struct(NestedUser) def new do %LocalUser{} end defmodule Context do def new do %LocalUser{} end end end test "local user" do assert LocalUser.new == %LocalUser{name: "john", nested: %LocalUser.NestedUser{}} assert LocalUser.Context.new == %LocalUser{name: "john", nested: %LocalUser.NestedUser{}} end defmodule NilUser do defstruct name: nil, contents: %{} end test "nil user" do assert %NilUser{} == %{__struct__: NilUser, name: nil, contents: %{}} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/module/000077500000000000000000000000001254730255300227175ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/module/locals_tracker_test.exs000066400000000000000000000136201254730255300274710ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Module.LocalsTrackerTest do use ExUnit.Case, async: true alias Module.LocalsTracker, as: D setup do {:ok, pid} = D.start_link {:ok, [pid: pid]} end ## Locals test "can add definitions", config do D.add_definition(config[:pid], :def, {:foo, 1}) D.add_definition(config[:pid], :defp, {:bar, 1}) end test "can add locals", config do D.add_definition(config[:pid], :def, {:foo, 1}) D.add_local(config[:pid], {:foo, 1}, {:bar, 1}) end test "public definitions are always reachable", config do D.add_definition(config[:pid], :def, {:public, 1}) assert {:public, 1} in D.reachable(config[:pid]) D.add_definition(config[:pid], :defmacro, {:public, 2}) assert {:public, 2} in D.reachable(config[:pid]) end test "private definitions are never reachable", config do D.add_definition(config[:pid], :defp, {:private, 1}) refute {:private, 1} in D.reachable(config[:pid]) D.add_definition(config[:pid], :defmacrop, {:private, 2}) refute {:private, 2} in D.reachable(config[:pid]) end test "private definitions are reachable when connected to local", config do D.add_definition(config[:pid], :defp, {:private, 1}) refute {:private, 1} in D.reachable(config[:pid]) D.add_local(config[:pid], {:private, 1}) assert {:private, 1} in D.reachable(config[:pid]) end test "private definitions are reachable when connected through a public one", config do D.add_definition(config[:pid], :defp, {:private, 1}) refute {:private, 1} in D.reachable(config[:pid]) D.add_definition(config[:pid], :def, {:public, 1}) D.add_local(config[:pid], {:public, 1}, {:private, 1}) assert {:private, 1} in D.reachable(config[:pid]) end test "can yank and reattach nodes", config do D.add_definition(config[:pid], :def, {:foo, 1}) D.add_local(config[:pid], {:foo, 1}, {:bar, 1}) D.add_definition(config[:pid], :defp, {:bar, 1}) {infoo, outfoo} = D.yank(config[:pid], {:foo, 1}) {inbar, outbar} = D.yank(config[:pid], {:bar, 1}) D.reattach(config[:pid], :defp, {:bar, 1}, {inbar, outbar}) D.reattach(config[:pid], :def, {:foo, 1}, {infoo, outfoo}) assert {:bar, 1} in D.reachable(config[:pid]) end @unused [ {{:private, 1}, :defp, 0} ] test "unused private definitions are marked as so", config do D.add_definition(config[:pid], :def, {:public, 1}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[private: 1], [{:unused_def, {:private, 1}, :defp}]} D.add_local(config[:pid], {:public, 1}, {:private, 1}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[], []} end @unused [ {{:private, 3}, :defp, 3} ] test "private definitions with unused default arguments", config do D.add_definition(config[:pid], :def, {:public, 1}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[private: 3], [{:unused_def, {:private, 3}, :defp}]} D.add_local(config[:pid], {:public, 1}, {:private, 3}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[], [unused_args: {:private, 3}]} end test "private definitions with some unused default arguments", config do D.add_definition(config[:pid], :def, {:public, 1}) D.add_local(config[:pid], {:public, 1}, {:private, 1}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[private: 3], [{:unused_args, {:private, 3}, 1}]} end test "private definitions with all used default arguments", config do D.add_definition(config[:pid], :def, {:public, 1}) D.add_local(config[:pid], {:public, 1}, {:private, 0}) unused = D.collect_unused_locals(config[:pid], @unused) assert unused == {[private: 3], []} end ## Defaults test "can add defaults", config do D.add_definition(config[:pid], :def, {:foo, 4}) D.add_defaults(config[:pid], :def, {:foo, 4}, 2) end test "defaults are reachable if public", config do D.add_definition(config[:pid], :def, {:foo, 4}) D.add_defaults(config[:pid], :def, {:foo, 4}, 2) assert {:foo, 2} in D.reachable(config[:pid]) assert {:foo, 3} in D.reachable(config[:pid]) end test "defaults are not reachable if private", config do D.add_definition(config[:pid], :defp, {:foo, 4}) D.add_defaults(config[:pid], :defp, {:foo, 4}, 2) refute {:foo, 2} in D.reachable(config[:pid]) refute {:foo, 3} in D.reachable(config[:pid]) end test "defaults are connected", config do D.add_definition(config[:pid], :defp, {:foo, 4}) D.add_defaults(config[:pid], :defp, {:foo, 4}, 2) D.add_local(config[:pid], {:foo, 2}) assert {:foo, 2} in D.reachable(config[:pid]) assert {:foo, 3} in D.reachable(config[:pid]) assert {:foo, 4} in D.reachable(config[:pid]) end ## Imports test "find imports from dispatch", config do D.add_import(config[:pid], nil, Module, {:concat, 1}) assert Module in D.imports_with_dispatch(config[:pid], {:concat, 1}) refute Module in D.imports_with_dispatch(config[:pid], {:unknown, 1}) end test "find import conflicts", config do refute {[Module], :conflict, 1} in D.collect_imports_conflicts(config[:pid], [conflict: 1]) # Calls outside local functions are not triggered D.add_import(config[:pid], nil, Module, {:conflict, 1}) refute {[Module], :conflict, 1} in D.collect_imports_conflicts(config[:pid], [conflict: 1]) D.add_local(config[:pid], {:foo, 2}) D.add_import(config[:pid], {:foo, 2}, Module, {:conflict, 1}) assert {[Module], :conflict, 1} in D.collect_imports_conflicts(config[:pid], [conflict: 1]) end defmodule NoPrivate do defmacrop foo(), do: bar() defp bar(), do: :baz def baz(), do: foo() end test "does not include unreachable locals" do assert NoPrivate.module_info(:functions) == [__info__: 1, baz: 0, module_info: 0, module_info: 1] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/module_test.exs000066400000000000000000000145311254730255300245030ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ModuleTest.ToBeUsed do def value, do: 1 defmacro __using__(_) do target = __CALLER__.module Module.put_attribute(target, :has_callback, true) Module.put_attribute(target, :before_compile, __MODULE__) Module.put_attribute(target, :after_compile, __MODULE__) Module.put_attribute(target, :before_compile, {__MODULE__, :callback}) quote do: (def line, do: __ENV__.line) end defmacro __before_compile__(env) do quote do: (def before_compile, do: unquote(env.vars)) end defmacro __after_compile__(%Macro.Env{module: ModuleTest.ToUse, vars: []}, bin) when is_binary(bin) do # IO.puts "HELLO" end defmacro callback(env) do value = Module.get_attribute(env.module, :has_callback) quote do def callback_value(true), do: unquote(value) end end end defmodule ModuleTest.ToUse do 32 = __ENV__.line # Moving the next line around can make tests fail var = 1 var # Not available in callbacks def callback_value(false), do: false use ModuleTest.ToBeUsed end defmodule ModuleTest do use ExUnit.Case, async: true Module.register_attribute __MODULE__, :register_example, accumulate: true, persist: true @register_example :it_works @register_example :still_works contents = quote do: (def eval_quoted_info, do: {__MODULE__, __ENV__.file, __ENV__.line}) Module.eval_quoted __MODULE__, contents, [], file: "sample.ex", line: 13 defmacrop in_module(block) do quote do defmodule Temp, unquote(block) :code.purge(Temp) :code.delete(Temp) end end test :in_memory do assert :code.which(__MODULE__) == :in_memory end ## Eval test :eval_quoted do assert eval_quoted_info() == {ModuleTest, "sample.ex", 13} end test :line_from_macro do assert ModuleTest.ToUse.line == 36 end ## Callbacks test :compile_callback_hook do assert ModuleTest.ToUse.callback_value(true) == true assert ModuleTest.ToUse.callback_value(false) == false end test :before_compile_callback_hook do assert ModuleTest.ToUse.before_compile == [] end test :on_definition do defmodule OnDefinition do @on_definition ModuleTest def hello(foo, bar) do foo + bar end end assert Process.get(ModuleTest.OnDefinition) == :called end def __on_definition__(env, kind, name, args, guards, expr) do Process.put(env.module, :called) assert env.module == ModuleTest.OnDefinition assert kind == :def assert name == :hello assert [{:foo, _, _}, {:bar, _, _}] = args assert [] = guards assert {:+, _, [{:foo, _, nil}, {:bar, _, nil}]} = expr end test :overridable_inside_before_compile do defmodule OverridableWithBeforeCompile do @before_compile ModuleTest end assert OverridableWithBeforeCompile.constant == 1 end test :alias_with_raw_atom do defmodule :"Elixir.ModuleTest.RawModule" do def hello, do: :world end assert RawModule.hello == :world end defmacro __before_compile__(_) do quote do def constant, do: 1 defoverridable constant: 0 end end ## Attributes test :reserved_attributes do assert List.keyfind(ExUnit.Server.__info__(:attributes), :behaviour, 0) == {:behaviour, [:gen_server]} end test :registered_attributes do assert [{:register_example, [:it_works]}, {:register_example, [:still_works]}] == Enum.filter __MODULE__.__info__(:attributes), &match?({:register_example, _}, &1) end @some_attribute [1] @other_attribute [3, 2, 1] test :inside_function_attributes do assert [1] = @some_attribute assert [3, 2, 1] = @other_attribute end ## Naming test :concat do assert Module.concat(Foo, Bar) == Foo.Bar assert Module.concat(Foo, :Bar) == Foo.Bar assert Module.concat(Foo, "Bar") == Foo.Bar assert Module.concat(Foo, Bar.Baz) == Foo.Bar.Baz assert Module.concat(Foo, "Bar.Baz") == Foo.Bar.Baz assert Module.concat(Bar, nil) == Elixir.Bar end test :safe_concat do assert Module.safe_concat(Foo, :Bar) == Foo.Bar assert_raise ArgumentError, fn -> Module.safe_concat SafeConcat, Doesnt.Exist end end test :split do module = Very.Long.Module.Name.And.Even.Longer assert Module.split(module) == ["Very", "Long", "Module", "Name", "And", "Even", "Longer"] assert Module.split("Elixir.Very.Long") == ["Very", "Long"] assert_raise FunctionClauseError, fn -> Module.split(:just_an_atom) end assert_raise FunctionClauseError, fn -> Module.split("Foo") end assert Module.concat(Module.split(module)) == module end test :__MODULE__ do assert Code.eval_string("__MODULE__.Foo") |> elem(0) == Foo end ## Creation test :defmodule do assert match?({:module, Defmodule, binary, 3} when is_binary(binary), defmodule Defmodule do 1 + 2 end) end test :defmodule_with_atom do assert match?({:module, :root_defmodule, _, _}, defmodule :root_defmodule do :ok end) end test :create do contents = quote do def world, do: true end {:module, ModuleCreateSample, _, _} = Module.create(ModuleCreateSample, contents, __ENV__) assert ModuleCreateSample.world end test :create_with_elixir_as_a_name do contents = quote do def world, do: true end assert_raise CompileError, fn -> {:module, Elixir, _, _} = Module.create(Elixir, contents, __ENV__) end end test :no_function_in_module_body do in_module do assert __ENV__.function == nil end end ## Definitions test :defines? do in_module do refute Module.defines? __MODULE__, {:foo, 0} def foo(), do: bar() assert Module.defines? __MODULE__, {:foo, 0} assert Module.defines? __MODULE__, {:foo, 0}, :def refute Module.defines? __MODULE__, {:bar, 0}, :defp defp bar(), do: :ok assert Module.defines? __MODULE__, {:bar, 0}, :defp refute Module.defines? __MODULE__, {:baz, 0}, :defmacro defmacro baz(), do: :ok assert Module.defines? __MODULE__, {:baz, 0}, :defmacro end end test :definitions_in do in_module do def foo(1, 2, 3), do: 4 assert Module.definitions_in(__MODULE__) == [foo: 3] assert Module.definitions_in(__MODULE__, :def) == [foo: 3] assert Module.definitions_in(__MODULE__, :defp) == [] end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/node_test.exs000066400000000000000000000004101254730255300241320ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule NodeTest do use ExUnit.Case test "start/3 and stop/0" do assert Node.stop == {:error, :not_found} assert {:ok, _} = Node.start(:hello, :shortnames, 15000) assert Node.stop() == :ok end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/option_parser_test.exs000066400000000000000000000312321254730255300260770ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule OptionParserTest do use ExUnit.Case, async: true test "parses boolean option" do assert OptionParser.parse(["--docs"]) == {[docs: true], [], []} end test "parses alias boolean option as the alias key" do assert OptionParser.parse(["-d"], aliases: [d: :docs]) == {[docs: true], [], []} end test "parses more than one boolean option" do assert OptionParser.parse(["--docs", "--compile"]) == {[docs: true, compile: true], [], []} end test "parses more than one boolean options as the alias" do assert OptionParser.parse(["-d", "--compile"], aliases: [d: :docs]) == {[docs: true, compile: true], [], []} end test "parses --key value option" do assert OptionParser.parse(["--source", "form_docs/"]) == {[source: "form_docs/"], [], []} end test "parses --key=value option" do assert OptionParser.parse(["--source=form_docs/", "other"]) == {[source: "form_docs/"], ["other"], []} end test "parses alias --key value option as the alias" do assert OptionParser.parse(["-s", "from_docs/"], aliases: [s: :source]) == {[source: "from_docs/"], [], []} end test "parses alias --key=value option as the alias" do assert OptionParser.parse(["-s=from_docs/", "other"], aliases: [s: :source]) == {[source: "from_docs/"], ["other"], []} end test "does not interpret undefined options with value as boolean" do assert OptionParser.parse(["--no-bool"]) == {[no_bool: true], [], []} assert OptionParser.parse(["--no-bool"], strict: []) == {[], [], [{"--no-bool", nil}]} assert OptionParser.parse(["--no-bool=...", "other"]) == {[no_bool: "..."], ["other"], []} end test "does not parse -- as an alias" do assert OptionParser.parse(["--s=from_docs/"], aliases: [s: :source]) == {[s: "from_docs/"], [], []} end test "does not parse - as a switch" do assert OptionParser.parse(["-source=from_docs/"], aliases: [s: :source]) == {[], [], [{"-source", "from_docs/"}]} end test "parses configured booleans" do assert OptionParser.parse(["--docs=false"], switches: [docs: :boolean]) == {[docs: false], [], []} assert OptionParser.parse(["--docs=true"], switches: [docs: :boolean]) == {[docs: true], [], []} assert OptionParser.parse(["--docs=other"], switches: [docs: :boolean]) == {[], [], [{"--docs", "other"}]} assert OptionParser.parse(["--docs="], switches: [docs: :boolean]) == {[], [], [{"--docs", ""}]} assert OptionParser.parse(["--docs", "foo"], switches: [docs: :boolean]) == {[docs: true], ["foo"], []} assert OptionParser.parse(["--no-docs", "foo"], switches: [docs: :boolean]) == {[docs: false], ["foo"], []} assert OptionParser.parse(["--no-docs=foo", "bar"], switches: [docs: :boolean]) == {[], ["bar"], [{"--no-docs", "foo"}]} assert OptionParser.parse(["--no-docs=", "bar"], switches: [docs: :boolean]) == {[], ["bar"], [{"--no-docs", ""}]} end test "does not set unparsed booleans" do assert OptionParser.parse(["foo"], switches: [docs: :boolean]) == {[], ["foo"], []} end test "keeps options on configured keep" do args = ["--require", "foo", "--require", "bar", "baz"] assert OptionParser.parse(args, switches: [require: :keep]) == {[require: "foo", require: "bar"], ["baz"], []} assert OptionParser.parse(["--require"], switches: [require: :keep]) == {[], [], [{"--require", nil}]} end test "parses configured strings" do assert OptionParser.parse(["--value", "1", "foo"], switches: [value: :string]) == {[value: "1"], ["foo"], []} assert OptionParser.parse(["--value=1", "foo"], switches: [value: :string]) == {[value: "1"], ["foo"], []} assert OptionParser.parse(["--value"], switches: [value: :string]) == {[], [], [{"--value", nil}]} assert OptionParser.parse(["--no-value"], switches: [value: :string]) == {[no_value: true], [], []} end test "parses configured integers" do assert OptionParser.parse(["--value", "1", "foo"], switches: [value: :integer]) == {[value: 1], ["foo"], []} assert OptionParser.parse(["--value=1", "foo"], switches: [value: :integer]) == {[value: 1], ["foo"], []} assert OptionParser.parse(["--value", "WAT", "foo"], switches: [value: :integer]) == {[], ["foo"], [{"--value", "WAT"}]} end test "parses configured integers with keep" do args = ["--value", "1", "--value", "2", "foo"] assert OptionParser.parse(args, switches: [value: [:integer, :keep]]) == {[value: 1, value: 2], ["foo"], []} args = ["--value=1", "foo", "--value=2", "bar"] assert OptionParser.parse(args, switches: [value: [:integer, :keep]]) == {[value: 1, value: 2], ["foo", "bar"], []} end test "parses configured floats" do assert OptionParser.parse(["--value", "1.0", "foo"], switches: [value: :float]) == {[value: 1.0], ["foo"], []} assert OptionParser.parse(["--value=1.0", "foo"], switches: [value: :float]) == {[value: 1.0], ["foo"], []} assert OptionParser.parse(["--value", "WAT", "foo"], switches: [value: :float]) == {[], ["foo"], [{"--value", "WAT"}]} end test "overrides options by default" do assert OptionParser.parse(["--require", "foo", "--require", "bar", "baz"]) == {[require: "bar"], ["baz"], []} end test "parses mixed options" do args = ["--source", "from_docs/", "--compile", "-x"] assert OptionParser.parse(args, aliases: [x: :x]) == {[source: "from_docs/", compile: true, x: true], [], []} end test "stops on first non option arguments" do args = ["--source", "from_docs/", "test/enum_test.exs", "--verbose"] assert OptionParser.parse_head(args) == {[source: "from_docs/"], ["test/enum_test.exs", "--verbose"], []} end test "stops on --" do options = OptionParser.parse(["--source", "foo", "--", "1", "2", "3"]) assert options == {[source: "foo"], ["1", "2", "3"], []} options = OptionParser.parse_head(["--source", "foo", "--", "1", "2", "3"]) assert options == {[source: "foo"], ["1", "2", "3"], []} options = OptionParser.parse(["--source", "foo", "bar", "--", "-x"]) assert options == {[source: "foo"], ["bar", "-x"], []} options = OptionParser.parse_head(["--source", "foo", "bar", "--", "-x"]) assert options == {[source: "foo"], ["bar", "--", "-x"], []} end test "goes beyond the first non option arguments" do args = ["--source", "from_docs/", "test/enum_test.exs", "--verbose"] assert OptionParser.parse(args) == {[source: "from_docs/", verbose: true], ["test/enum_test.exs"], []} end test "parses more than one key/value options" do assert OptionParser.parse(["--source", "from_docs/", "--docs", "show"]) == {[source: "from_docs/", docs: "show"], [], []} end test "collects multiple invalid options" do args = ["--bad", "opt", "foo", "-o", "bad", "bar"] assert OptionParser.parse(args, switches: [bad: :integer]) == {[], ["foo", "bar"], [{"--bad", "opt"}, {"-o", "bad"}]} end test "parses more than one key/value options using strict" do assert OptionParser.parse(["--source", "from_docs/", "--docs", "show"], strict: [source: :string, docs: :string]) == {[source: "from_docs/", docs: "show"], [], []} assert OptionParser.parse(["--source", "from_docs/", "--doc", "show"], strict: [source: :string, docs: :string]) == {[source: "from_docs/"], ["show"], [{"--doc", nil}]} assert OptionParser.parse(["--source", "from_docs/", "--doc=show"], strict: [source: :string, docs: :string]) == {[source: "from_docs/"], [], [{"--doc", nil}]} end test "parses - as argument" do assert OptionParser.parse(["-a", "-", "-", "-b", "-"], aliases: [b: :boo]) == {[boo: "-"], ["-"], [{"-a", "-"}]} assert OptionParser.parse(["--foo", "-", "-b", "-"], strict: [foo: :boolean, boo: :string], aliases: [b: :boo]) == {[foo: true, boo: "-"], ["-"], []} end test "multi-word option" do config = [switches: [hello_world: :boolean]] assert OptionParser.next(["--hello-world"], config) == {:ok, :hello_world, true, []} assert OptionParser.next(["--no-hello-world"], config) == {:ok, :hello_world, false, []} assert OptionParser.next(["--hello-world"], []) == {:ok, :hello_world, true, []} assert OptionParser.next(["--no-hello-world"], []) == {:ok, :no_hello_world, true, []} assert OptionParser.next(["--hello_world"], []) == {:invalid, "--hello_world", nil, []} assert OptionParser.next(["--no-hello_world"], []) == {:invalid, "--no-hello_world", nil, []} assert OptionParser.next(["--no-hello-world"], strict: []) == {:undefined, "--no-hello-world", nil, []} assert OptionParser.next(["--no-hello_world"], strict: []) == {:undefined, "--no-hello_world", nil, []} config = [strict: [hello_world: :boolean]] assert OptionParser.next(["--hello-world"], config) == {:ok, :hello_world, true, []} assert OptionParser.next(["--no-hello-world"], config) == {:ok, :hello_world, false, []} assert OptionParser.next(["--hello_world"], config) == {:undefined, "--hello_world", nil, []} assert OptionParser.next(["--no-hello_world"], config) == {:undefined, "--no-hello_world", nil, []} end test "next strict: good options" do config = [strict: [str: :string, int: :integer, bool: :boolean]] assert OptionParser.next(["--str", "hello", "..."], config) == {:ok, :str, "hello", ["..."]} assert OptionParser.next(["--int=13", "..."], config) == {:ok, :int, 13, ["..."]} assert OptionParser.next(["--bool=false", "..."], config) == {:ok, :bool, false, ["..."]} assert OptionParser.next(["--no-bool", "..."], config) == {:ok, :bool, false, ["..."]} assert OptionParser.next(["--bool", "..."], config) == {:ok, :bool, true, ["..."]} assert OptionParser.next(["..."], config) == {:error, ["..."]} end test "next strict: unknown options" do config = [strict: [bool: :boolean]] assert OptionParser.next(["--str", "13", "..."], config) == {:undefined, "--str", nil, ["13", "..."]} assert OptionParser.next(["--int=hello", "..."], config) == {:undefined, "--int", "hello", ["..."]} assert OptionParser.next(["-no-bool=other", "..."], config) == {:undefined, "-no-bool", "other", ["..."]} end test "next strict: bad type" do config = [strict: [str: :string, int: :integer, bool: :boolean]] assert OptionParser.next(["--str", "13", "..."], config) == {:ok, :str, "13", ["..."]} assert OptionParser.next(["--int=hello", "..."], config) == {:invalid, "--int", "hello", ["..."]} assert OptionParser.next(["--int", "hello", "..."], config) == {:invalid, "--int", "hello", ["..."]} assert OptionParser.next(["--bool=other", "..."], config) == {:invalid, "--bool", "other", ["..."]} end test "next strict: missing value" do config = [strict: [str: :string, int: :integer, bool: :boolean]] assert OptionParser.next(["--str"], config) == {:invalid, "--str", nil, []} assert OptionParser.next(["--int"], config) == {:invalid, "--int", nil, []} assert OptionParser.next(["--bool=", "..."], config) == {:invalid, "--bool", "", ["..."]} assert OptionParser.next(["--no-bool=", "..."], config) == {:invalid, "--no-bool", "", ["..."]} end test "split" do assert OptionParser.split(~S[]) == [] assert OptionParser.split(~S[foo]) == ["foo"] assert OptionParser.split(~S[foo bar]) == ["foo", "bar"] assert OptionParser.split(~S[ foo bar ]) == ["foo", "bar"] assert OptionParser.split(~S[foo\ bar]) == ["foo bar"] assert OptionParser.split(~S[foo" bar"]) == ["foo bar"] assert OptionParser.split(~S[foo\" bar\"]) == ["foo\"", "bar\""] assert OptionParser.split(~S[foo "\ bar\""]) == ["foo", "\\ bar\""] assert OptionParser.split(~S[foo '\"bar"\'\ ']) == ["foo", "\\\"bar\"'\\ "] end test "to_argv" do assert OptionParser.to_argv([foo_bar: "baz"]) == ["--foo-bar", "baz"] assert OptionParser.to_argv([bool: true, bool: false, discarded: nil]) == ["--bool", "--no-bool"] end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/path_test.exs000066400000000000000000000224451254730255300241550ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule PathTest do use ExUnit.Case, async: true import PathHelpers if :file.native_name_encoding == :utf8 do test :wildcard_with_utf8 do File.mkdir_p(tmp_path("héllò")) assert Path.wildcard(tmp_path("héllò")) == [tmp_path("héllò")] after File.rm_rf tmp_path("héllò") end end test :wildcard do hello = tmp_path("wildcard/.hello") world = tmp_path("wildcard/.hello/world") File.mkdir_p(world) assert Path.wildcard(tmp_path("wildcard/*/*")) == [] assert Path.wildcard(tmp_path("wildcard/**/*")) == [] assert Path.wildcard(tmp_path("wildcard/?hello/world")) == [] assert Path.wildcard(tmp_path("wildcard/*/*"), match_dot: true) == [world] assert Path.wildcard(tmp_path("wildcard/**/*"), match_dot: true) == [hello, world] assert Path.wildcard(tmp_path("wildcard/?hello/world"), match_dot: true) == [world] after File.rm_rf tmp_path("wildcard") end if windows? do test :relative_win do assert Path.relative("C:/usr/local/bin") == "usr/local/bin" assert Path.relative("C:\\usr\\local\\bin") == "usr\\local\\bin" assert Path.relative("C:usr\\local\\bin") == "usr\\local\\bin" assert Path.relative("/usr/local/bin") == "usr/local/bin" assert Path.relative("usr/local/bin") == "usr/local/bin" assert Path.relative("../usr/local/bin") == "../usr/local/bin" assert Path.relative_to("D:/usr/local/foo", "D:/usr/") == "local/foo" assert Path.relative_to("D:/usr/local/foo", "d:/usr/") == "local/foo" assert Path.relative_to("d:/usr/local/foo", "D:/usr/") == "local/foo" assert Path.relative_to("D:/usr/local/foo", "d:") == "usr/local/foo" assert Path.relative_to("D:/usr/local/foo", "D:") == "usr/local/foo" end test :type_win do assert Path.type("C:/usr/local/bin") == :absolute assert Path.type('C:\\usr\\local\\bin') == :absolute assert Path.type("C:usr\\local\\bin") == :volumerelative assert Path.type("/usr/local/bin") == :volumerelative assert Path.type('usr/local/bin') == :relative assert Path.type("../usr/local/bin") == :relative end test :split_win do assert Path.split("C:\\foo\\bar") == ["c:/", "foo", "bar"] assert Path.split("C:/foo/bar") == ["c:/", "foo", "bar"] end else test :relative_unix do assert Path.relative("/usr/local/bin") == "usr/local/bin" assert Path.relative("usr/local/bin") == "usr/local/bin" assert Path.relative("../usr/local/bin") == "../usr/local/bin" assert Path.relative(['/usr', ?/, "local/bin"]) == "usr/local/bin" end test :type_unix do assert Path.type("/usr/local/bin") == :absolute assert Path.type("usr/local/bin") == :relative assert Path.type("../usr/local/bin") == :relative assert Path.type('/usr/local/bin') == :absolute assert Path.type('usr/local/bin') == :relative assert Path.type('../usr/local/bin') == :relative assert Path.type(['/usr/', 'local/bin']) == :absolute assert Path.type(['usr/', 'local/bin']) == :relative assert Path.type(['../usr', '/local/bin']) == :relative end end test :relative_to_cwd do assert Path.relative_to_cwd(__ENV__.file) == Path.relative_to(__ENV__.file, System.cwd!) assert Path.relative_to_cwd(to_char_list(__ENV__.file)) == Path.relative_to(to_char_list(__ENV__.file), to_char_list(System.cwd!)) end test :absname do assert (Path.absname("/") |> strip_drive_letter_if_windows) == "/" assert (Path.absname("/foo") |> strip_drive_letter_if_windows) == "/foo" assert (Path.absname("/./foo") |> strip_drive_letter_if_windows) == "/foo" assert (Path.absname("/foo/bar") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.absname("/foo/bar/") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.absname("/foo/bar/../bar") |> strip_drive_letter_if_windows) == "/foo/bar/../bar" assert Path.absname("bar", "/foo") == "/foo/bar" assert Path.absname("bar/", "/foo") == "/foo/bar" assert Path.absname("bar/.", "/foo") == "/foo/bar/." assert Path.absname("bar/../bar", "/foo") == "/foo/bar/../bar" assert Path.absname("bar/../bar", "foo") == "foo/bar/../bar" assert Path.absname(["bar/", ?., ?., ["/bar"]], "/foo") == "/foo/bar/../bar" end test :expand_path_with_user_home do home = System.user_home! assert home == Path.expand("~") assert home == Path.expand('~') assert is_binary Path.expand("~/foo") assert is_binary Path.expand('~/foo') assert Path.expand("~/file") == Path.join(home, "file") assert Path.expand("~/file", "whatever") == Path.join(home, "file") assert Path.expand("file", Path.expand("~")) == Path.expand("~/file") assert Path.expand("file", "~") == Path.join(home, "file") assert Path.expand("~file") == Path.join(System.cwd!, "file") end test :expand_path do assert (Path.expand("/") |> strip_drive_letter_if_windows) == "/" assert (Path.expand("/foo") |> strip_drive_letter_if_windows) == "/foo" assert (Path.expand("/./foo") |> strip_drive_letter_if_windows) == "/foo" assert (Path.expand("/foo/bar") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.expand("/foo/bar/") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.expand("/foo/bar/.") |> strip_drive_letter_if_windows)== "/foo/bar" assert (Path.expand("/foo/bar/../bar") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.expand("bar", "/foo") |> strip_drive_letter_if_windows)== "/foo/bar" assert (Path.expand("bar/", "/foo") |> strip_drive_letter_if_windows)== "/foo/bar" assert (Path.expand("bar/.", "/foo") |> strip_drive_letter_if_windows)== "/foo/bar" assert (Path.expand("bar/../bar", "/foo") |> strip_drive_letter_if_windows)== "/foo/bar" assert (Path.expand("../bar/../bar", "/foo/../foo/../foo") |> strip_drive_letter_if_windows) == "/bar" assert (Path.expand(['..', ?/, "bar/../bar"], '/foo/../foo/../foo') |> strip_drive_letter_if_windows) == "/bar" assert (Path.expand("/..") |> strip_drive_letter_if_windows) == "/" assert Path.expand("bar/../bar", "foo") == Path.expand("foo/bar") end test :relative_to do assert Path.relative_to("/usr/local/foo", "/usr/local") == "foo" assert Path.relative_to("/usr/local/foo", "/") == "usr/local/foo" assert Path.relative_to("/usr/local/foo", "/etc") == "/usr/local/foo" assert Path.relative_to("/usr/local/foo", "/usr/local/foo") == "/usr/local/foo" assert Path.relative_to("usr/local/foo", "usr/local") == "foo" assert Path.relative_to("usr/local/foo", "etc") == "usr/local/foo" assert Path.relative_to('usr/local/foo', "etc") == "usr/local/foo" assert Path.relative_to("usr/local/foo", "usr/local") == "foo" assert Path.relative_to(["usr", ?/, 'local/foo'], 'usr/local') == "foo" end test :rootname do assert Path.rootname("~/foo/bar.ex", ".ex") == "~/foo/bar" assert Path.rootname("~/foo/bar.exs", ".ex") == "~/foo/bar.exs" assert Path.rootname("~/foo/bar.old.ex", ".ex") == "~/foo/bar.old" assert Path.rootname([?~, '/foo/bar', ".old.ex"], '.ex') == "~/foo/bar.old" end test :extname do assert Path.extname("foo.erl") == ".erl" assert Path.extname("~/foo/bar") == "" assert Path.extname('foo.erl') == ".erl" assert Path.extname('~/foo/bar') == "" end test :dirname do assert Path.dirname("/foo/bar.ex") == "/foo" assert Path.dirname("foo/bar.ex") == "foo" assert Path.dirname("~/foo/bar.ex") == "~/foo" assert Path.dirname("/foo/bar/baz/") == "/foo/bar/baz" assert Path.dirname([?~, "/foo", '/bar.ex']) == "~/foo" end test :basename do assert Path.basename("foo") == "foo" assert Path.basename("/foo/bar") == "bar" assert Path.basename("/") == "" assert Path.basename("~/foo/bar.ex", ".ex") == "bar" assert Path.basename("~/foo/bar.exs", ".ex") == "bar.exs" assert Path.basename("~/for/bar.old.ex", ".ex") == "bar.old" assert Path.basename([?~, "/for/bar", '.old.ex'], ".ex") == "bar.old" end test :join do assert Path.join([""]) == "" assert Path.join(["foo"]) == "foo" assert Path.join(["/", "foo", "bar"]) == "/foo/bar" assert Path.join(["~", "foo", "bar"]) == "~/foo/bar" assert Path.join(['/foo/', "/bar/"]) == "/foo/bar" end test :join_two do assert Path.join("/foo", "bar") == "/foo/bar" assert Path.join("~", "foo") == "~/foo" assert Path.join("", "bar") == "bar" assert Path.join("bar", "") == "bar" assert Path.join("", "/bar") == "bar" assert Path.join("/bar", "") == "/bar" assert Path.join("foo", "/bar") == "foo/bar" assert Path.join("/foo", "/bar") == "/foo/bar" assert Path.join("/foo", "/bar") == "/foo/bar" assert Path.join("/foo", "./bar") == "/foo/./bar" assert Path.join([?/, "foo"], "./bar") == "/foo/./bar" end test :split do assert Path.split("") == [] assert Path.split("foo") == ["foo"] assert Path.split("/foo/bar") == ["/", "foo", "bar"] assert Path.split([?/, "foo/bar"]) == ["/", "foo", "bar"] end if windows? do defp strip_drive_letter_if_windows([_d, ?:|rest]), do: rest defp strip_drive_letter_if_windows(<<_d, ?:, rest::binary>>), do: rest else defp strip_drive_letter_if_windows(path), do: path end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/port_test.exs000066400000000000000000000010531254730255300241750ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule PortTest do use ExUnit.Case, async: true test "info/1,2 with registered name" do {:ok, port} = :gen_udp.open(0) assert Port.info(port, :links) == {:links, [self()]} assert Port.info(port, :registered_name) == {:registered_name, []} Process.register(port, __MODULE__) assert Port.info(port, :registered_name) == {:registered_name, __MODULE__} :ok = :gen_udp.close(port) assert Port.info(port, :registered_name) == nil assert Port.info(port) == nil end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/process_test.exs000066400000000000000000000044111254730255300246700ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ProcessTest do use ExUnit.Case, async: true test "group_leader/2 and group_leader/0" do another = spawn_link(fn -> :timer.sleep(1000) end) assert Process.group_leader(self, another) assert Process.group_leader == another end test "monitoring functions are inlined by the compiler" do assert expand(quote(do: Process.monitor(pid())), __ENV__) == quote(do: :erlang.monitor(:process, pid())) end test "info/2" do pid = spawn fn -> end Process.exit(pid, :kill) assert Process.info(pid, :backtrace) == nil end test "info/2 with registered name" do pid = spawn fn -> end Process.exit(pid, :kill) assert Process.info(pid, :registered_name) == nil assert Process.info(self, :registered_name) == {:registered_name, []} Process.register(self, __MODULE__) assert Process.info(self, :registered_name) == {:registered_name, __MODULE__} end test "exit(pid, :normal) does not cause the target process to exit" do pid = spawn_link fn -> receive do :done -> nil end end trap = Process.flag(:trap_exit, true) true = Process.exit(pid, :normal) refute_receive {:EXIT, ^pid, :normal} assert Process.alive?(pid) # now exit the process for real so it doesn't hang around true = Process.exit(pid, :abnormal) assert_receive {:EXIT, ^pid, :abnormal} refute Process.alive?(pid) Process.flag(:trap_exit, trap) end test "exit(pid, :normal) makes the process receive a message if it traps exits" do parent = self() pid = spawn_link fn -> Process.flag(:trap_exit, true) receive do {:EXIT, ^parent, :normal} -> send(parent, {:ok, self()}) end end refute_receive _ Process.exit(pid, :normal) assert_receive {:ok, ^pid} refute Process.alive?(pid) end test "exit(self(), :normal) causes the calling process to exit" do trap = Process.flag(:trap_exit, true) pid = spawn_link fn -> Process.exit(self(), :normal) end assert_receive {:EXIT, ^pid, :normal} refute Process.alive?(pid) Process.flag(:trap_exit, trap) end defp expand(expr, env) do {expr, _env} = :elixir_exp.expand(expr, env) expr end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/protocol_test.exs000066400000000000000000000256001254730255300250560ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ProtocolTest do use ExUnit.Case, async: true defprotocol Sample do @type t :: any @doc "Ok" @spec ok(t) :: boolean def ok(thing) end defprotocol WithAny do @fallback_to_any true @doc "Ok" def ok(thing) end defprotocol Derivable do def ok(a) end defimpl Derivable, for: Any do defmacro __deriving__(module, struct, options) do quote do defimpl Derivable, for: unquote(module) do def ok(arg) do {:ok, arg, unquote(Macro.escape(struct)), unquote(options)} end end end end def ok(arg) do {:ok, arg} end end defimpl WithAny, for: Map do def ok(map) do {:ok, map} end end defimpl WithAny, for: Any do def ok(any) do {:ok, any} end end defmodule NoImplStruct do defstruct a: 0, b: 0 end defmodule ImplStruct do @derive [WithAny, Derivable] defstruct a: 0, b: 0 defimpl Sample do def ok(struct) do Unknown.undefined(struct) end end end test "protocol implementations without any" do assert is_nil Sample.impl_for(:foo) assert is_nil Sample.impl_for(fn(x) -> x end) assert is_nil Sample.impl_for(1) assert is_nil Sample.impl_for(1.1) assert is_nil Sample.impl_for([]) assert is_nil Sample.impl_for([1, 2, 3]) assert is_nil Sample.impl_for({}) assert is_nil Sample.impl_for({1, 2, 3}) assert is_nil Sample.impl_for("foo") assert is_nil Sample.impl_for(<<1>>) assert is_nil Sample.impl_for(%{}) assert is_nil Sample.impl_for(self) assert is_nil Sample.impl_for(hd(:erlang.ports)) assert is_nil Sample.impl_for(make_ref) assert Sample.impl_for(%ImplStruct{}) == Sample.ProtocolTest.ImplStruct assert Sample.impl_for(%NoImplStruct{}) == nil end test "protocol implementation with any and structs fallback" do assert WithAny.impl_for(%NoImplStruct{}) == WithAny.Any assert WithAny.impl_for(%ImplStruct{}) == WithAny.Any # Derived assert WithAny.impl_for(%{__struct__: "foo"}) == WithAny.Map assert WithAny.impl_for(%{}) == WithAny.Map assert WithAny.impl_for(self) == WithAny.Any end test "protocol not implemented" do assert_raise Protocol.UndefinedError, "protocol ProtocolTest.Sample not implemented for :foo", fn -> Sample.ok(:foo) end end test "protocol documentation" do import PathHelpers write_beam(defprotocol SampleDocsProto do @type t :: any @doc "Ok" @spec ok(t) :: boolean def ok(thing) end) docs = Code.get_docs(SampleDocsProto, :docs) assert {{:ok, 1}, _, :def, [{:thing, _, nil}], "Ok"} = List.keyfind(docs, {:ok, 1}, 0) end test "protocol keeps underlying UndefinedFunctionError" do assert_raise UndefinedFunctionError, fn -> WithAll.ok(%ImplStruct{}) end end test "protocol defines callbacks" do if :erlang.system_info(:otp_release) >= '18' do assert get_callbacks(Sample, :ok, 1) == [{:type, [9], :fun, [{:type, [9], :product, [{:user_type, [9], :t, []}]}, {:type, [9], :boolean, []}]}] assert get_callbacks(WithAny, :ok, 1) == [{:type, [16], :fun, [{:type, [16], :product, [{:user_type, [16], :t, []}]}, {:type, [16], :term, []}]}] else assert get_callbacks(Sample, :ok, 1) == [{:type, 9, :fun, [{:type, 9, :product, [{:type, 9, :t, []}]}, {:type, 9, :boolean, []}]}] assert get_callbacks(WithAny, :ok, 1) == [{:type, 16, :fun, [{:type, 16, :product, [{:type, 16, :t, []}]}, {:type, 16, :term, []}]}] end end test "protocol defines functions and attributes" do assert Sample.__protocol__(:module) == Sample assert Sample.__protocol__(:functions) == [ok: 1] refute Sample.__protocol__(:consolidated?) assert Sample.__info__(:attributes)[:protocol] == [fallback_to_any: false] assert WithAny.__protocol__(:module) == WithAny assert WithAny.__protocol__(:functions) == [ok: 1] refute WithAny.__protocol__(:consolidated?) assert WithAny.__info__(:attributes)[:protocol] == [fallback_to_any: true] end test "defimpl" do module = Module.concat(Sample, ImplStruct) assert module.__impl__(:for) == ImplStruct assert module.__impl__(:target) == module assert module.__impl__(:protocol) == Sample assert module.__info__(:attributes)[:impl] == [protocol: Sample, for: ImplStruct] end test "defimpl with implicit derive" do module = Module.concat(WithAny, ImplStruct) assert module.__impl__(:for) == ImplStruct assert module.__impl__(:target) == WithAny.Any assert module.__impl__(:protocol) == WithAny assert module.__info__(:attributes)[:impl] == [protocol: WithAny, for: ImplStruct] end test "defimpl with explicit derive" do module = Module.concat(Derivable, ImplStruct) assert module.__impl__(:for) == ImplStruct assert module.__impl__(:target) == module assert module.__impl__(:protocol) == Derivable assert module.__info__(:attributes)[:impl] == [protocol: Derivable, for: ImplStruct] end test "defimpl with multiple for" do defprotocol Multi do def test(a) end defimpl Multi, for: [Atom, Integer] do def test(a), do: a end assert Multi.test(1) == 1 assert Multi.test(:a) == :a end defp get_callbacks(module, name, arity) do callbacks = for {:callback, info} <- module.__info__(:attributes), do: hd(info) List.keyfind(callbacks, {name, arity}, 0) |> elem(1) end test "derives protocol implicitly" do struct = %ImplStruct{a: 1, b: 1} assert WithAny.ok(struct) == {:ok, struct} struct = %NoImplStruct{a: 1, b: 1} assert WithAny.ok(struct) == {:ok, struct} end test "derives protocol explicitly" do struct = %ImplStruct{a: 1, b: 1} assert Derivable.ok(struct) == {:ok, struct, %ImplStruct{}, []} assert_raise Protocol.UndefinedError, fn -> struct = %NoImplStruct{a: 1, b: 1} Derivable.ok(struct) end end test "derives protocol explicitly with options" do defmodule AnotherStruct do @derive [{Derivable, :ok}] @derive [WithAny] defstruct a: 0, b: 0 end struct = struct AnotherStruct, a: 1, b: 1 assert Derivable.ok(struct) == {:ok, struct, struct(AnotherStruct), :ok} end test "derive protocol explicitly via API" do defmodule InlineStruct do defstruct a: 0, b: 0 end require Protocol assert Protocol.derive(Derivable, InlineStruct, :oops) == :ok struct = struct InlineStruct, a: 1, b: 1 assert Derivable.ok(struct) == {:ok, struct, struct(InlineStruct), :oops} end test "derived implementation keeps local file/line info" do assert ProtocolTest.WithAny.ProtocolTest.ImplStruct.__info__(:compile)[:source] == String.to_char_list(__ENV__.file) end test "cannot derive without any implementation" do assert_raise ArgumentError, ~r"#{inspect Sample.Any} is not available, cannot derive #{inspect Sample}", fn -> defmodule NotCompiled do @derive [Sample] defstruct hello: :world end end end end path = Path.expand("../ebin", __DIR__) File.mkdir_p!(path) compile = fn {:module, module, binary, _} -> File.write!("#{path}/#{module}.beam", binary) end defmodule Protocol.ConsolidationTest do use ExUnit.Case, async: true compile.( defprotocol Sample do @type t :: any @doc "Ok" @spec ok(t) :: boolean def ok(thing) end ) compile.( defprotocol WithAny do @fallback_to_any true @doc "Ok" def ok(thing) end ) defimpl WithAny, for: Map do def ok(map) do {:ok, map} end end defimpl WithAny, for: Any do def ok(any) do {:ok, any} end end defmodule NoImplStruct do defstruct a: 0, b: 0 end defmodule ImplStruct do @derive [WithAny] defstruct a: 0, b: 0 defimpl Sample do def ok(struct) do Unknown.undefined(struct) end end end Code.append_path(path) # Any is ignored because there is no fallback :code.purge(Sample) :code.delete(Sample) {:ok, binary} = Protocol.consolidate(Sample, [Any, ImplStruct]) :code.load_binary(Sample, 'protocol_test.exs', binary) # Any should be moved to the end :code.purge(WithAny) :code.delete(WithAny) {:ok, binary} = Protocol.consolidate(WithAny, [Any, ImplStruct, Map]) :code.load_binary(WithAny, 'protocol_test.exs', binary) test "consolidated?/1" do assert Protocol.consolidated?(WithAny) refute Protocol.consolidated?(Enumerable) end test "consolidated implementations without any" do assert is_nil Sample.impl_for(:foo) assert is_nil Sample.impl_for(fn(x) -> x end) assert is_nil Sample.impl_for(1) assert is_nil Sample.impl_for(1.1) assert is_nil Sample.impl_for([]) assert is_nil Sample.impl_for([1, 2, 3]) assert is_nil Sample.impl_for({}) assert is_nil Sample.impl_for({1, 2, 3}) assert is_nil Sample.impl_for("foo") assert is_nil Sample.impl_for(<<1>>) assert is_nil Sample.impl_for(self) assert is_nil Sample.impl_for(%{}) assert is_nil Sample.impl_for(hd(:erlang.ports)) assert is_nil Sample.impl_for(make_ref) assert Sample.impl_for(%ImplStruct{}) == Sample.Protocol.ConsolidationTest.ImplStruct assert Sample.impl_for(%NoImplStruct{}) == nil end test "consolidated implementations with any and tuple fallback" do assert WithAny.impl_for(%NoImplStruct{}) == WithAny.Any assert WithAny.impl_for(%ImplStruct{}) == WithAny.Any # Derived assert WithAny.impl_for(%{__struct__: "foo"}) == WithAny.Map assert WithAny.impl_for(%{}) == WithAny.Map assert WithAny.impl_for(self) == WithAny.Any end test "consolidation keeps docs" do docs = Code.get_docs(Sample, :docs) assert {{:ok, 1}, _, :def, [{:thing, _, nil}], "Ok"} = List.keyfind(docs, {:ok, 1}, 0) end test "consolidated keeps callbacks" do callbacks = for {:callback, info} <- Sample.__info__(:attributes), do: hd(info) assert callbacks != [] end test "consolidation errors on missing beams" do defprotocol NoBeam, do: nil assert Protocol.consolidate(String, []) == {:error, :not_a_protocol} assert Protocol.consolidate(NoBeam, []) == {:error, :no_beam_info} end test "consolidation updates attributes" do assert Sample.__protocol__(:consolidated?) assert WithAny.__protocol__(:consolidated?) end test "consolidation extracts protocols" do protos = Protocol.extract_protocols([:code.lib_dir(:elixir, :ebin)]) assert Enumerable in protos assert Inspect in protos end test "consolidation extracts implementations" do protos = Protocol.extract_impls(Enumerable, [:code.lib_dir(:elixir, :ebin)]) assert List in protos assert Function in protos end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/range_test.exs000066400000000000000000000015501254730255300243070ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule RangeTest do use ExUnit.Case, async: true test :precedence do assert Enum.to_list(1..3+2) == [1, 2, 3, 4, 5] assert 1..3 |> Enum.to_list == [1, 2, 3] end test :op do assert (1..3).first == 1 assert (1..3).last == 3 end test :range? do assert Range.range?(1..3) refute Range.range?(0) end test :enum do refute Enum.empty?(1..1) assert Enum.member?(1..3, 2) refute Enum.member?(1..3, 0) refute Enum.member?(1..3, 4) refute Enum.member?(3..1, 0) refute Enum.member?(3..1, 4) assert Enum.count(1..3) == 3 assert Enum.count(3..1) == 3 assert Enum.map(1..3, &(&1 * 2)) == [2, 4, 6] assert Enum.map(3..1, &(&1 * 2)) == [6, 4, 2] end test :inspect do assert inspect(1..3) == "1..3" assert inspect(3..1) == "3..1" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/record_test.exs000066400000000000000000000070361254730255300244760ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule RecordTest do use ExUnit.Case, async: true require Record test "extract/2 extracts information from an Erlang file" do assert Record.extract(:file_info, from_lib: "kernel/include/file.hrl") == [size: :undefined, type: :undefined, access: :undefined, atime: :undefined, mtime: :undefined, ctime: :undefined, mode: :undefined, links: :undefined, major_device: :undefined, minor_device: :undefined, inode: :undefined, uid: :undefined, gid: :undefined] end test "extract/2 handles nested records too" do namespace = Record.extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl")[:namespace] assert is_tuple(namespace) assert elem(namespace, 0) == :xmlNamespace end test "extract/2 with defstruct" do defmodule StructExtract do defstruct Record.extract(:file_info, from_lib: "kernel/include/file.hrl") end assert %{__struct__: StructExtract, size: :undefined} = StructExtract.__struct__ end test "extract_all/1 extracts all records information from an Erlang file" do all_extract = Record.extract_all(from_lib: "kernel/include/file.hrl") assert length(all_extract) == 2 # has been stable over the very long time assert all_extract[:file_info] assert all_extract[:file_descriptor] end # We need indirection to avoid warnings defp record?(data, kind) do Record.is_record(data, kind) end test "is_record/2" do assert record?({User, "meg", 27}, User) refute record?({User, "meg", 27}, Author) refute record?(13, Author) end # We need indirection to avoid warnings defp record?(data) do Record.is_record(data) end test "is_record/1" do assert record?({User, "john", 27}) refute record?({"john", 27}) refute record?(13) end Record.defrecord :timestamp, [:date, :time] Record.defrecord :user, __MODULE__, name: "john", age: 25 Record.defrecordp :file_info, Record.extract(:file_info, from_lib: "kernel/include/file.hrl") Record.defrecordp :certificate, :OTPCertificate, Record.extract(:OTPCertificate, from_lib: "public_key/include/public_key.hrl") test "records generates macros that generates tuples" do record = user() assert user(record, :name) == "john" assert user(record, :age) == 25 record = user(record, name: "meg") assert user(record, :name) == "meg" assert elem(record, user(:name)) == "meg" assert elem(record, 0) == RecordTest user(name: name) = record assert name == "meg" assert user(:name) == 1 end test "records with no tag" do assert elem(file_info(), 0) == :file_info end test "records with dynamic arguments" do record = file_info() assert file_info(record, :size) == :undefined record = user() assert user(record) == [name: "john", age: 25] assert user(user()) == [name: "john", age: 25] msg = "expected argument to be a literal atom, literal keyword or a :file_info record, " <> "got runtime: {RecordTest, \"john\", 25}" assert_raise ArgumentError, msg, fn -> file_info(record) end end test "records visibility" do assert macro_exported?(__MODULE__, :user, 0) refute macro_exported?(__MODULE__, :file_info, 1) end test "records with no defaults" do record = timestamp() assert timestamp(record, :date) == nil assert timestamp(record, :time) == nil record = timestamp(date: :foo, time: :bar) assert timestamp(record, :date) == :foo assert timestamp(record, :time) == :bar end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/regex_test.exs000066400000000000000000000212461254730255300243310ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule RegexTest do use ExUnit.Case, async: true test :multiline do refute Regex.match?(~r/^b$/, "a\nb\nc") assert Regex.match?(~r/^b$/m, "a\nb\nc") end test :precedence do assert {"aa", :unknown} |> elem(0) =~ ~r/(a)\1/ end test :backreference do assert "aa" =~ ~r/(a)\1/ end test :compile! do assert Regex.regex?(Regex.compile!("foo")) assert_raise Regex.CompileError, ~r/position 0$/, fn -> Regex.compile!("*foo") end end test :compile do {:ok, regex} = Regex.compile("foo") assert Regex.regex?(regex) assert {:error, _} = Regex.compile("*foo") assert {:error, _} = Regex.compile("foo", "y") assert {:error, _} = Regex.compile("foo", "uy") end test :compile_with_erl_opts do {:ok, regex} = Regex.compile("foo\\sbar", [:dotall, {:newline, :anycrlf}]) assert "foo\nbar" =~ regex end test :regex? do assert Regex.regex?(~r/foo/) refute Regex.regex?(0) end test :source do src = "foo" assert Regex.source(Regex.compile!(src)) == src assert Regex.source(~r/#{src}/) == src src = "\a\b\d\e\f\n\r\s\t\v" assert Regex.source(Regex.compile!(src)) == src assert Regex.source(~r/#{src}/) == src src = "\a\\b\\d\\e\f\n\r\\s\t\v" assert Regex.source(Regex.compile!(src)) == src assert Regex.source(~r/#{src}/) == src end test :literal_source do assert Regex.source(Regex.compile!("foo")) == "foo" assert Regex.source(~r"foo") == "foo" assert Regex.re_pattern(Regex.compile!("foo")) == Regex.re_pattern(~r"foo") assert Regex.source(Regex.compile!("\a\b\d\e\f\n\r\s\t\v")) == "\a\b\d\e\f\n\r\s\t\v" assert Regex.source(~r<\a\b\d\e\f\n\r\s\t\v>) == "\a\\b\\d\\e\f\n\r\\s\t\v" assert Regex.re_pattern(Regex.compile!("\a\b\d\e\f\n\r\s\t\v")) == Regex.re_pattern(~r"\a\010\177\033\f\n\r \t\v") assert Regex.source(Regex.compile!("\a\\b\\d\e\f\n\r\\s\t\v")) == "\a\\b\\d\e\f\n\r\\s\t\v" assert Regex.source(~r<\a\\b\\d\\e\f\n\r\\s\t\v>) == "\a\\\\b\\\\d\\\\e\f\n\r\\\\s\t\v" assert Regex.re_pattern(Regex.compile!("\a\\b\\d\e\f\n\r\\s\t\v")) == Regex.re_pattern(~r"\a\b\d\e\f\n\r\s\t\v") end test :opts do assert Regex.opts(Regex.compile!("foo", "i")) == "i" end test :unicode do assert "olá" =~ ~r"\p{Latin}$"u refute "£" =~ ~r/\p{Lu}/u # Non breaking space matches [[:space:]] with unicode assert <<0xA0::utf8>> =~ ~r/[[:space:]]/u assert <<0xA0::utf8>> =~ ~r/\s/u assert <>> =~ ~r/<.>/ refute <>> =~ ~r/<.>/u end test :names do assert Regex.names(~r/(?foo)/) == ["FOO"] end test :match? do assert Regex.match?(~r/foo/, "foo") refute Regex.match?(~r/foo/, "FOO") assert Regex.match?(~r/foo/i, "FOO") assert Regex.match?(~r/\d{1,3}/i, "123") assert Regex.match?(~r/foo/, "afooa") refute Regex.match?(~r/^foo/, "afooa") assert Regex.match?(~r/^foo/, "fooa") refute Regex.match?(~r/foo$/, "afooa") assert Regex.match?(~r/foo$/, "afoo") end test :named_captures do assert Regex.named_captures(~r/(?c)(?d)/, "abcd") == %{"bar" => "d", "foo" => "c"} assert Regex.named_captures(~r/c(?d)/, "abcd") == %{"foo" => "d"} assert Regex.named_captures(~r/c(?d)/, "no_match") == nil assert Regex.named_captures(~r/c(?d|e)/, "abcd abce") == %{"foo" => "d"} assert Regex.named_captures(~r/c(.)/, "cat") == %{} end test :sigil_R do assert Regex.match?(~R/f#{1,3}o/, "f#o") end test :run do assert Regex.run(~r"c(d)", "abcd") == ["cd", "d"] assert Regex.run(~r"e", "abcd") == nil end test :run_with_all_names do assert Regex.run(~r/c(?d)/, "abcd", capture: :all_names) == ["d"] assert Regex.run(~r/c(?d)/, "no_match", capture: :all_names) == nil assert Regex.run(~r/c(?d|e)/, "abcd abce", capture: :all_names) == ["d"] end test :run_with_indexes do assert Regex.run(~r"c(d)", "abcd", return: :index) == [{2, 2}, {3, 1}] assert Regex.run(~r"e", "abcd", return: :index) == nil end test :scan do assert Regex.scan(~r"c(d|e)", "abcd abce") == [["cd", "d"], ["ce", "e"]] assert Regex.scan(~r"c(?:d|e)", "abcd abce") == [["cd"], ["ce"]] assert Regex.scan(~r"e", "abcd") == [] end test :scan_with_all_names do assert Regex.scan(~r/cd/, "abcd", capture: :all_names) == [] assert Regex.scan(~r/c(?d)/, "abcd", capture: :all_names) == [["d"]] assert Regex.scan(~r/c(?d)/, "no_match", capture: :all_names) == [] assert Regex.scan(~r/c(?d|e)/, "abcd abce", capture: :all_names) == [["d"], ["e"]] end test :split do assert Regex.split(~r",", "") == [""] assert Regex.split(~r",", "", trim: true) == [] assert Regex.split(~r",", "", trim: true, parts: 2) == [] assert Regex.split(~r"=", "key=") == ["key", ""] assert Regex.split(~r"=", "=value") == ["", "value"] assert Regex.split(~r" ", "foo bar baz") == ["foo", "bar", "baz"] assert Regex.split(~r" ", "foo bar baz", parts: :infinity) == ["foo", "bar", "baz"] assert Regex.split(~r" ", "foo bar baz", parts: 10) == ["foo", "bar", "baz"] assert Regex.split(~r" ", "foo bar baz", parts: 2) == ["foo", "bar baz"] assert Regex.split(~r" ", " foo bar baz ") == ["", "foo", "bar", "baz", ""] assert Regex.split(~r" ", " foo bar baz ", trim: true) == ["foo", "bar", "baz"] assert Regex.split(~r" ", " foo bar baz ", parts: 2) == ["", "foo bar baz "] assert Regex.split(~r" ", " foo bar baz ", trim: true, parts: 2) == ["foo", "bar baz "] end test :split_on do assert Regex.split(~r/()abc()/, "xabcxabcx", on: :none) == ["xabcxabcx"] assert Regex.split(~r/()abc()/, "xabcxabcx", on: :all_but_first) == ["x", "abc", "x", "abc", "x"] assert Regex.split(~r/(?)abc(?)/, "xabcxabcx", on: [:first, :last]) == ["x", "abc", "x", "abc", "x"] assert Regex.split(~r/(?)abc(?)/, "xabcxabcx", on: [:last, :first]) == ["xabc", "xabc", "x"] assert Regex.split(~r/a(?b)c/, "abc", on: [:second]) == ["a", "c"] assert Regex.split(~r/a(?b)c|a(?d)c/, "abc adc abc", on: [:second]) == ["a", "c adc a", "c"] assert Regex.split(~r/a(?b)c|a(?d)c/, "abc adc abc", on: [:second, :fourth]) == ["a", "c a", "c a", "c"] end test :replace do assert Regex.replace(~r(d), "abc", "d") == "abc" assert Regex.replace(~r(b), "abc", "d") == "adc" assert Regex.replace(~r(b), "abc", "[\\0]") == "a[b]c" assert Regex.replace(~r[(b)], "abc", "[\\1]") == "a[b]c" assert Regex.replace(~r[(b)], "abc", "[\\2]") == "a[]c" assert Regex.replace(~r[(b)], "abc", "[\\3]") == "a[]c" assert Regex.replace(~r(b), "abc", "[\\g{0}]") == "a[b]c" assert Regex.replace(~r[(b)], "abc", "[\\g{1}]") == "a[b]c" assert Regex.replace(~r(b), "abcbe", "d") == "adcde" assert Regex.replace(~r(b), "abcbe", "d", global: false) == "adcbe" assert Regex.replace(~r/ /, "first third", "\\second\\") == "first\\second\\third" assert Regex.replace(~r/ /, "first third", "\\\\second\\\\") == "first\\second\\third" assert Regex.replace(~r[a(b)c], "abcabc", fn -> "ac" end) == "acac" assert Regex.replace(~r[a(b)c], "abcabc", fn "abc" -> "ac" end) == "acac" assert Regex.replace(~r[a(b)c], "abcabc", fn "abc", "b" -> "ac" end) == "acac" assert Regex.replace(~r[a(b)c], "abcabc", fn "abc", "b", "" -> "ac" end) == "acac" assert Regex.replace(~r[a(b)c], "abcabc", fn "abc", "b" -> "ac" end, global: false) == "acabc" end test :ungreedy do assert Regex.run(~r/[\d ]+/, "1 2 3 4 5"), ["1 2 3 4 5"] assert Regex.run(~r/[\d ]?+/, "1 2 3 4 5"), ["1"] assert Regex.run(~r/[\d ]+/r, "1 2 3 4 5"), ["1"] assert Regex.run(~r/[\d ]+/U, "1 2 3 4 5"), ["1"] end test :escape do assert matches_escaped?(".") refute matches_escaped?(".", "x") assert matches_escaped?("[\w]") refute matches_escaped?("[\w]", "x") assert matches_escaped?("\\") assert matches_escaped?("\\xff", "\\xff") refute matches_escaped?("\\xff", "\xff") assert matches_escaped?("(") assert matches_escaped?("()") assert matches_escaped?("(?:foo)") assert matches_escaped?("\\A \\z") assert matches_escaped?(" x ") assert matches_escaped?("  x    x ") # unicode spaces here assert matches_escaped?("# lol") assert matches_escaped?("\\A.^$*+?()[{\\| \t\n\xff\\z #hello\x{202F}\x{205F}") end defp matches_escaped?(string) do matches_escaped?(string, string) end defp matches_escaped?(string, match) do Regex.match? ~r/#{Regex.escape(string)}/simxu, match end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/set_test.exs000066400000000000000000000130061254730255300240050ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ # A TestSet implementation used only for testing. defmodule TestSet do defstruct list: [] def new(list \\ []) when is_list(list) do %TestSet{list: list} end def reduce(%TestSet{list: list}, acc, fun) do Enumerable.reduce(list, acc, fun) end def member?(%TestSet{list: list}, v) do v in list end def size(%TestSet{list: list}) do length(list) end end defmodule SetTest.Common do defmacro __using__(_) do quote location: :keep do defp new_set(list \\ []) do Enum.into list, set_impl.new end defp new_set(list, fun) do Enum.into list, set_impl.new, fun end defp int_set() do Enum.into [1, 2, 3], set_impl.new end test "delete/2" do result = Set.delete(new_set([1, 2, 3]), 2) assert Set.equal?(result, new_set([1, 3])) end test "delete/2 with match" do refute Set.member?(Set.delete(int_set, 1), 1) assert Set.member?(Set.delete(int_set, 1.0), 1) end test "difference/2" do result = Set.difference(new_set([1, 2, 3]), new_set([3])) assert Set.equal?(result, new_set([1, 2])) end test "difference/2 with match" do refute Set.member?(Set.difference(int_set, new_set([1])), 1) assert Set.member?(Set.difference(int_set, new_set([1.0])), 1) end test "difference/2 with other set" do result = Set.difference(new_set([1, 2, 3]), TestSet.new([3])) assert Set.equal?(result, new_set([1, 2])) end test "disjoint?/2" do assert Set.disjoint?(new_set([1, 2, 3]), new_set([4, 5, 6])) refute Set.disjoint?(new_set([1, 2, 3]), new_set([3, 4, 5])) end test "disjoint/2 with other set" do assert Set.disjoint?(new_set([1, 2, 3]), TestSet.new([4, 5, 6])) refute Set.disjoint?(new_set([1, 2, 3]), TestSet.new([3, 4, 5])) end test "equal?/2" do assert Set.equal?(new_set([1, 2, 3]), new_set([3, 2, 1])) refute Set.equal?(new_set([1, 2, 3]), new_set([3.0, 2.0, 1.0])) end test "equal?/2 with other set" do assert Set.equal?(new_set([1, 2, 3]), TestSet.new([3, 2, 1])) refute Set.equal?(new_set([1, 2, 3]), TestSet.new([3.0, 2.0, 1.0])) end test "intersection/2" do result = Set.intersection(new_set([1, 2, 3]), new_set([2, 3, 4])) assert Set.equal?(result, new_set([2, 3])) end test "intersection/2 with match" do assert Set.member?(Set.intersection(int_set, new_set([1])), 1) refute Set.member?(Set.intersection(int_set, new_set([1.0])), 1) end test "intersection/2 with other set" do result = Set.intersection(new_set([1, 2, 3]), TestSet.new([2, 3, 4])) assert Set.equal?(result, new_set([2, 3])) end test "member?/2" do assert Set.member?(new_set([1, 2, 3]), 2) refute Set.member?(new_set([1, 2, 3]), 4) refute Set.member?(new_set([1, 2, 3]), 1.0) end test "put/2" do result = Set.put(new_set([1, 2]), 3) assert Set.equal?(result, new_set([1, 2, 3])) end test "put/2 with match" do assert Set.size(Set.put(int_set, 1)) == 3 assert Set.size(Set.put(int_set, 1.0)) == 4 end test "size/1" do assert Set.size(new_set([1, 2, 3])) == 3 end test "subset?/2" do assert Set.subset?(new_set([1, 2]), new_set([1, 2, 3])) refute Set.subset?(new_set([1, 2, 3]), new_set([1, 2])) end test "subset/2 with match?" do assert Set.subset?(new_set([1]), int_set) refute Set.subset?(new_set([1.0]), int_set) end test "subset?/2 with other set" do assert Set.subset?(new_set([1, 2]), TestSet.new([1, 2, 3])) refute Set.subset?(new_set([1, 2, 3]), TestSet.new([1, 2])) end test "to_list/1" do assert Set.to_list(new_set([1, 2, 3])) |> Enum.sort == [1, 2, 3] end test "union/2" do result = Set.union(new_set([1, 2, 3]), new_set([2, 3, 4])) assert Set.equal?(result, new_set([1, 2, 3, 4])) end test "union/2 with match" do assert Set.size(Set.union(int_set, new_set([1]))) == 3 assert Set.size(Set.union(int_set, new_set([1.0]))) == 4 end test "union/2 with other set" do result = Set.union(new_set([1, 2, 3]), TestSet.new([2, 3, 4])) assert Set.equal?(result, new_set([1, 2, 3, 4])) end test "is enumerable" do assert Enum.member?(int_set, 1) refute Enum.member?(int_set, 1.0) assert Enum.sort(int_set) == [1, 2, 3] end test "is collectable" do assert Set.equal?(new_set([1, 1, 2, 3, 3, 3]), new_set([1, 2, 3])) assert Set.equal?(new_set([1, 1, 2, 3, 3, 3], &(&1 * 2)), new_set([2, 4, 6])) end test "is zippable" do set = new_set(1..8) list = Dict.to_list(set) assert Enum.zip(list, list) == Enum.zip(set, set) set = new_set(1..100) list = Dict.to_list(set) assert Enum.zip(list, list) == Enum.zip(set, set) end test "unsupported set" do assert_raise ArgumentError, "unsupported set: :bad_set", fn -> Set.to_list :bad_set end end end end end defmodule Set.HashSetTest do use ExUnit.Case, async: true use SetTest.Common doctest Set def set_impl, do: HashSet end defmodule Set.MapSetTest do use ExUnit.Case, async: true use SetTest.Common doctest Set def set_impl, do: MapSet end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/stream_test.exs000066400000000000000000000627601254730255300245200ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule StreamTest do use ExUnit.Case, async: true defmodule PDict do defstruct [] defimpl Collectable do def into(struct) do {struct, fn _, {:cont, x} -> Process.put(:stream_cont, [x|Process.get(:stream_cont)]) _, :done -> Process.put(:stream_done, true) _, :halt -> Process.put(:stream_halt, true) end} end end end test "streams as enumerables" do stream = Stream.map([1, 2, 3], &(&1 * 2)) # Reduce assert Enum.map(stream, &(&1 + 1)) == [3, 5, 7] # Member assert Enum.member?(stream, 4) refute Enum.member?(stream, 1) # Count assert Enum.count(stream) == 3 end test "streams are composable" do stream = Stream.map([1, 2, 3], &(&1 * 2)) assert is_lazy(stream) stream = Stream.map(stream, &(&1 + 1)) assert is_lazy(stream) assert Enum.to_list(stream) == [3, 5, 7] end test "chunk/2, chunk/3 and chunk/4" do assert Stream.chunk([1, 2, 3, 4, 5], 2) |> Enum.to_list == [[1, 2], [3, 4]] assert Stream.chunk([1, 2, 3, 4, 5], 2, 2, [6]) |> Enum.to_list == [[1, 2], [3, 4], [5, 6]] assert Stream.chunk([1, 2, 3, 4, 5, 6], 3, 2) |> Enum.to_list == [[1, 2, 3], [3, 4, 5]] assert Stream.chunk([1, 2, 3, 4, 5, 6], 2, 3) |> Enum.to_list == [[1, 2], [4, 5]] assert Stream.chunk([1, 2, 3, 4, 5, 6], 3, 2, []) |> Enum.to_list == [[1, 2, 3], [3, 4, 5], [5, 6]] assert Stream.chunk([1, 2, 3, 4, 5, 6], 3, 3, []) |> Enum.to_list == [[1, 2, 3], [4, 5, 6]] assert Stream.chunk([1, 2, 3, 4, 5], 4, 4, 6..10) |> Enum.to_list == [[1, 2, 3, 4], [5, 6, 7, 8]] end test "chunk/4 is zippable" do stream = Stream.chunk([1, 2, 3, 4, 5, 6], 3, 2, []) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "chunk/4 is haltable" do assert 1..10 |> Stream.take(6) |> Stream.chunk(4, 4, [7, 8]) |> Enum.to_list == [[1, 2, 3, 4], [5, 6, 7, 8]] assert 1..10 |> Stream.take(6) |> Stream.chunk(4, 4, [7, 8]) |> Stream.take(3) |> Enum.to_list == [[1, 2, 3, 4], [5, 6, 7, 8]] assert 1..10 |> Stream.take(6) |> Stream.chunk(4, 4, [7, 8]) |> Stream.take(2) |> Enum.to_list == [[1, 2, 3, 4], [5, 6, 7, 8]] assert 1..10 |> Stream.take(6) |> Stream.chunk(4, 4, [7, 8]) |> Stream.take(1) |> Enum.to_list == [[1, 2, 3, 4]] assert 1..6 |> Stream.take(6) |> Stream.chunk(4, 4, [7, 8]) |> Enum.to_list == [[1, 2, 3, 4], [5, 6, 7, 8]] end test "chunk_by/2" do stream = Stream.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1)) assert is_lazy(stream) assert Enum.to_list(stream) == [[1], [2, 2], [3], [4, 4, 6], [7, 7]] assert stream |> Stream.take(3) |> Enum.to_list == [[1], [2, 2], [3]] assert 1..10 |> Stream.chunk(2) |> Enum.take(2) == [[1, 2], [3, 4]] end test "chunk_by/2 is zippable" do stream = Stream.chunk_by([1, 2, 2, 3], &(rem(&1, 2) == 1)) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "concat/1" do stream = Stream.concat([1..3, [], [4, 5, 6], [], 7..9]) assert is_function(stream) assert Enum.to_list(stream) == [1, 2, 3, 4, 5, 6, 7, 8, 9] assert Enum.take(stream, 5) == [1, 2, 3, 4, 5] stream = Stream.concat([1..3, [4, 5, 6], Stream.cycle(7..100)]) assert is_function(stream) assert Enum.take(stream, 13) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] end test "concat/2" do stream = Stream.concat(1..3, 4..6) assert is_function(stream) assert Stream.cycle(stream) |> Enum.take(16) == [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4] stream = Stream.concat(1..3, []) assert is_function(stream) assert Stream.cycle(stream) |> Enum.take(5) == [1, 2, 3, 1, 2] stream = Stream.concat(1..6, Stream.cycle(7..9)) assert is_function(stream) assert Stream.drop(stream, 3) |> Enum.take(13) == [4, 5, 6, 7, 8, 9, 7, 8, 9, 7, 8, 9, 7] stream = Stream.concat(Stream.cycle(1..3), Stream.cycle(4..6)) assert is_function(stream) assert Enum.take(stream, 13) == [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1] end test "concat/2 does not intercept wrapped lazy enumeration" do # concat returns a lazy enumeration that does not halt assert Stream.concat([[0], Stream.map([1, 2, 3], & &1), [4]]) |> Stream.take_while(fn x -> x <= 4 end) |> Enum.to_list == [0, 1, 2, 3, 4] # concat returns a lazy enumeration that does halts assert Stream.concat([[0], Stream.take_while(1..6, &(&1 <= 3)), [4]]) |> Stream.take_while(fn x -> x <= 4 end) |> Enum.to_list == [0, 1, 2, 3, 4] end test "cycle/1" do stream = Stream.cycle([1, 2, 3]) assert is_function(stream) assert Stream.cycle([1, 2, 3]) |> Stream.take(5) |> Enum.to_list == [1, 2, 3, 1, 2] assert Enum.take(stream, 5) == [1, 2, 3, 1, 2] end test "cycle/1 is zippable" do stream = Stream.cycle([1, 2, 3]) assert Enum.zip(1..6, [1, 2, 3, 1, 2, 3]) == Enum.zip(1..6, stream) end test "cycle/1 with inner stream" do assert [1, 2, 3] |> Stream.take(2) |> Stream.cycle |> Enum.take(4) == [1, 2, 1, 2] end test "dedup/1 is lazy" do assert is_lazy Stream.dedup([1, 2, 3]) end test "dedup/1" do assert Stream.dedup([1, 1, 2, 1, 1, 2, 1]) |> Enum.to_list == [1, 2, 1, 2, 1] assert Stream.dedup([2, 1, 1, 2, 1]) |> Enum.to_list == [2, 1, 2, 1] assert Stream.dedup([1, 2, 3, 4]) |> Enum.to_list == [1, 2, 3, 4] assert Stream.dedup([1, 1.0, 2.0, 2]) |> Enum.to_list == [1, 1.0, 2.0, 2] assert Stream.dedup([]) |> Enum.to_list == [] assert Stream.dedup([nil, nil, true, {:value, true}]) |> Enum.to_list == [nil, true, {:value, true}] assert Stream.dedup([nil]) |> Enum.to_list == [nil] end test "dedup_by/2" do assert Stream.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) |> Enum.to_list == [{1, :x}, {2, :y}, {1, :x}] end test "drop/2" do stream = Stream.drop(1..10, 5) assert is_lazy(stream) assert Enum.to_list(stream) == [6, 7, 8, 9, 10] assert Enum.to_list(Stream.drop(1..5, 0)) == [1, 2, 3, 4, 5] assert Enum.to_list(Stream.drop(1..3, 5)) == [] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.drop(nats, 2) |> Enum.take(5) == [3, 4, 5, 6, 7] end test "drop/2 with negative count" do stream = Stream.drop(1..10, -5) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 3, 4, 5] stream = Stream.drop(1..10, -5) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "drop/2 with negative count stream entries" do par = self pid = spawn_link fn -> Enum.each Stream.drop(&inbox_stream/2, -3), fn x -> send par, {:stream, x} end end send pid, {:stream, 1} send pid, {:stream, 2} send pid, {:stream, 3} refute_receive {:stream, 1} send pid, {:stream, 4} assert_receive {:stream, 1} send pid, {:stream, 5} assert_receive {:stream, 2} refute_receive {:stream, 3} end test "drop_while/2" do stream = Stream.drop_while(1..10, &(&1 <= 5)) assert is_lazy(stream) assert Enum.to_list(stream) == [6, 7, 8, 9, 10] assert Enum.to_list(Stream.drop_while(1..5, &(&1 <= 0))) == [1, 2, 3, 4, 5] assert Enum.to_list(Stream.drop_while(1..3, &(&1 <= 5))) == [] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.drop_while(nats, &(&1 <= 5)) |> Enum.take(5) == [6, 7, 8, 9, 10] end test "each/2" do Process.put(:stream_each, []) stream = Stream.each([1, 2, 3], fn x -> Process.put(:stream_each, [x|Process.get(:stream_each)]) end) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 3] assert Process.get(:stream_each) == [3, 2, 1] end test "filter/2" do stream = Stream.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) assert is_lazy(stream) assert Enum.to_list(stream) == [2] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.filter(nats, &(rem(&1, 2) == 0)) |> Enum.take(5) == [2, 4, 6, 8, 10] end test "filter_map/3" do stream = Stream.filter_map([1, 2, 3], fn(x) -> rem(x, 2) == 0 end, &(&1 * 2)) assert is_lazy(stream) assert Enum.to_list(stream) == [4] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.filter_map(nats, &(rem(&1, 2) == 0), &(&1 * 2)) |> Enum.take(5) == [4, 8, 12, 16, 20] end test "flat_map/2" do stream = Stream.flat_map([1, 2, 3], &[&1, &1 * 2]) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 2, 4, 3, 6] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.flat_map(nats, &[&1, &1 * 2]) |> Enum.take(6) == [1, 2, 2, 4, 3, 6] end test "flat_map/2 does not intercept wrapped lazy enumeration" do # flat_map returns a lazy enumeration that does not halt assert [1, 2, 3, -1, -2] |> Stream.flat_map(fn x -> Stream.map([x, x+1], & &1) end) |> Stream.take_while(fn x -> x >= 0 end) |> Enum.to_list == [1, 2, 2, 3, 3, 4] # flat_map returns a lazy enumeration that does halts assert [1, 2, 3, -1, -2] |> Stream.flat_map(fn x -> Stream.take_while([x, x+1, x+2], &(&1 <= x + 1)) end) |> Stream.take_while(fn x -> x >= 0 end) |> Enum.to_list == [1, 2, 2, 3, 3, 4] # flat_map returns a lazy enumeration that does halts wrapped in an enumerable assert [1, 2, 3, -1, -2] |> Stream.flat_map(fn x -> Stream.concat([x], Stream.take_while([x+1, x+2], &(&1 <= x + 1))) end) |> Stream.take_while(fn x -> x >= 0 end) |> Enum.to_list == [1, 2, 2, 3, 3, 4] end test "flat_map/2 is zippable" do stream = [1, 2, 3, -1, -2] |> Stream.flat_map(fn x -> Stream.map([x, x+1], & &1) end) |> Stream.take_while(fn x -> x >= 0 end) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "flat_map/2 does not leave inner stream suspended" do stream = Stream.flat_map [1, 2, 3], fn i -> Stream.resource(fn -> i end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_flat_map, true) end) end Process.put(:stream_flat_map, false) assert stream |> Enum.take(3) == [1, 2, 3] assert Process.get(:stream_flat_map) end test "flat_map/2 does not leave outer stream suspended" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_flat_map, true) end) stream = Stream.flat_map(stream, fn i -> [i, i + 1, i + 2] end) Process.put(:stream_flat_map, false) assert stream |> Enum.take(3) == [1, 2, 3] assert Process.get(:stream_flat_map) end test "flat_map/2 closes on error" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_flat_map, true) end) stream = Stream.flat_map(stream, fn _ -> throw(:error) end) Process.put(:stream_flat_map, false) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_flat_map) end test "flat_map/2 with inner flat_map/2" do stream = Stream.flat_map(1..5, fn x -> Stream.flat_map([x], fn x -> x .. x * x end) |> Stream.map(& &1 * 1) end) assert Enum.take(stream, 5) == [1, 2, 3, 4, 3] end test "flat_map/2 properly halts both inner and outer stream when inner stream is halted" do # Fixes a bug that, when the inner stream was done, # sending it a halt would cause it to return the # inner stream was halted, forcing flat_map to get # the next value from the outer stream, evaluate it, # get annother inner stream, just to halt it. assert [1, 2] # 2 should never be used |> Stream.flat_map(fn 1 -> Stream.repeatedly(fn -> 1 end) end) |> Stream.flat_map(fn 1 -> Stream.repeatedly(fn -> 1 end) end) |> Enum.take(1) == [1] end test "interval/1" do stream = Stream.interval(10) now = :os.timestamp assert Enum.take(stream, 5) == [0, 1, 2, 3, 4] assert :timer.now_diff(:os.timestamp, now) > 50000 end test "into/2 and run/1" do Process.put(:stream_cont, []) Process.put(:stream_done, false) Process.put(:stream_halt, false) stream = Stream.into([1, 2, 3], %PDict{}) assert is_lazy(stream) assert Stream.run(stream) == :ok assert Process.get(:stream_cont) == [3, 2, 1] assert Process.get(:stream_done) refute Process.get(:stream_halt) stream = Stream.into(fn _, _ -> raise "error" end, %PDict{}) catch_error(Stream.run(stream)) assert Process.get(:stream_halt) end test "into/3" do Process.put(:stream_cont, []) Process.put(:stream_done, false) Process.put(:stream_halt, false) stream = Stream.into([1, 2, 3], %PDict{}, fn x -> x*2 end) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 3] assert Process.get(:stream_cont) == [6, 4, 2] assert Process.get(:stream_done) refute Process.get(:stream_halt) end test "into/2 with halting" do Process.put(:stream_cont, []) Process.put(:stream_done, false) Process.put(:stream_halt, false) stream = Stream.into([1, 2, 3], %PDict{}) assert is_lazy(stream) assert Enum.take(stream, 1) == [1] assert Process.get(:stream_cont) == [1] assert Process.get(:stream_done) refute Process.get(:stream_halt) end test "transform/3" do stream = Stream.transform([1, 2, 3], 0, &{[&1, &2], &1 + &2}) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 0, 2, 1, 3, 3] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.transform(nats, 0, &{[&1, &2], &1 + &2}) |> Enum.take(6) == [1, 0, 2, 1, 3, 3] end test "transform/3 with halt" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_transform, true) end) stream = Stream.transform(stream, 0, fn i, acc -> if acc < 3, do: {[i], acc + 1}, else: {:halt, acc} end) Process.put(:stream_transform, false) assert Enum.to_list(stream) == [1, 2, 3] assert Process.get(:stream_transform) end test "iterate/2" do stream = Stream.iterate(0, &(&1+2)) assert Enum.take(stream, 5) == [0, 2, 4, 6, 8] stream = Stream.iterate(5, &(&1+2)) assert Enum.take(stream, 5) == [5, 7, 9, 11, 13] # Only calculate values if needed stream = Stream.iterate("HELLO", &raise/1) assert Enum.take(stream, 1) == ["HELLO"] end test "map/2" do stream = Stream.map([1, 2, 3], &(&1 * 2)) assert is_lazy(stream) assert Enum.to_list(stream) == [2, 4, 6] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.map(nats, &(&1 * 2)) |> Enum.take(5) == [2, 4, 6, 8, 10] assert Stream.map(nats, &(&1 - 2)) |> Stream.map(&(&1 * 2)) |> Enum.take(3) == [-2, 0, 2] end test "reject/2" do stream = Stream.reject([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 3] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.reject(nats, &(rem(&1, 2) == 0)) |> Enum.take(5) == [1, 3, 5, 7, 9] end test "repeatedly/1" do stream = Stream.repeatedly(fn -> 1 end) assert Enum.take(stream, 5) == [1, 1, 1, 1, 1] stream = Stream.repeatedly(&:random.uniform/0) [r1, r2] = Enum.take(stream, 2) assert r1 != r2 end test "resource/3 closes on errors" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) Process.put(:stream_resource, false) stream = Stream.map(stream, fn x -> if x > 2, do: throw(:error), else: x end) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_resource) end test "resource/3 is zippable" do stream = Stream.resource(fn -> 1 end, fn 10 -> {:halt, 10} acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) list = Enum.to_list(stream) Process.put(:stream_resource, false) assert Enum.zip(list, list) == Enum.zip(stream, stream) assert Process.get(:stream_resource) end test "resource/3 halts with inner list" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc, acc+1, acc+2], acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) Process.put(:stream_resource, false) assert Enum.take(stream, 5) == [1, 2, 3, 2, 3] assert Process.get(:stream_resource) end test "resource/3 closes on errors with inner list" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc, acc+1, acc+2], acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) Process.put(:stream_resource, false) stream = Stream.map(stream, fn x -> if x > 2, do: throw(:error), else: x end) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_resource) end test "resource/3 is zippable with inner list" do stream = Stream.resource(fn -> 1 end, fn 10 -> {:halt, 10} acc -> {[acc, acc+1, acc+2], acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) list = Enum.to_list(stream) Process.put(:stream_resource, false) assert Enum.zip(list, list) == Enum.zip(stream, stream) assert Process.get(:stream_resource) end test "resource/3 halts with inner enum" do stream = Stream.resource(fn -> 1 end, fn acc -> {acc..acc+2, acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) Process.put(:stream_resource, false) assert Enum.take(stream, 5) == [1, 2, 3, 2, 3] assert Process.get(:stream_resource) end test "resource/3 closes on errors with inner enum" do stream = Stream.resource(fn -> 1 end, fn acc -> {acc..acc+2, acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) Process.put(:stream_resource, false) stream = Stream.map(stream, fn x -> if x > 2, do: throw(:error), else: x end) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_resource) end test "resource/3 is zippable with inner enum" do stream = Stream.resource(fn -> 1 end, fn 10 -> {:halt, 10} acc -> {acc..acc+2, acc + 1} end, fn _ -> Process.put(:stream_resource, true) end) list = Enum.to_list(stream) Process.put(:stream_resource, false) assert Enum.zip(list, list) == Enum.zip(stream, stream) assert Process.get(:stream_resource) end test "scan/2" do stream = Stream.scan(1..5, &(&1 + &2)) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 3, 6, 10, 15] assert Stream.scan([], &(&1 + &2)) |> Enum.to_list == [] end test "scan/3" do stream = Stream.scan(1..5, 0, &(&1 + &2)) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 3, 6, 10, 15] assert Stream.scan([], 0, &(&1 + &2)) |> Enum.to_list == [] end test "take/2" do stream = Stream.take(1..1000, 5) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 3, 4, 5] assert Enum.to_list(Stream.take(1..1000, 0)) == [] assert Enum.to_list(Stream.take([], 5)) == [] assert Enum.to_list(Stream.take(1..3, 5)) == [1, 2, 3] nats = Stream.iterate(1, &(&1 + 1)) assert Enum.to_list(Stream.take(nats, 5)) == [1, 2, 3, 4, 5] stream = Stream.drop(1..100, 5) assert Stream.take(stream, 5) |> Enum.to_list == [6, 7, 8, 9, 10] stream = 1..5 |> Stream.take(10) |> Stream.drop(15) assert {[], []} = Enum.split(stream, 5) stream = 1..20 |> Stream.take(10 + 5) |> Stream.drop(4) assert Enum.to_list(stream) == [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] end test "take/2 with negative count" do Process.put(:stream_each, []) stream = Stream.take(1..100, -5) assert is_lazy(stream) stream = Stream.each(stream, &Process.put(:stream_each, [&1|Process.get(:stream_each)])) assert Enum.to_list(stream) == [96, 97, 98, 99, 100] assert Process.get(:stream_each) == [100, 99, 98, 97, 96] end test "take/2 is zippable" do stream = Stream.take(1..1000, 5) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "take_every/2" do assert 1..10 |> Stream.take_every(2) |> Enum.to_list == [1, 3, 5, 7, 9] assert 1..10 |> Stream.drop(2) |> Stream.take_every(2) |> Stream.drop(1) |> Enum.to_list == [5, 7, 9] assert 1..10 |> Stream.take_every(0) |> Enum.to_list == [] assert [] |> Stream.take_every(10) |> Enum.to_list == [] end test "take_every/2 without non-negative integer" do assert_raise FunctionClauseError, fn -> Stream.take_every(1..10, -1) end assert_raise FunctionClauseError, fn -> Stream.take_every(1..10, 3.33) end end test "take_while/2" do stream = Stream.take_while(1..1000, &(&1 <= 5)) assert is_lazy(stream) assert Enum.to_list(stream) == [1, 2, 3, 4, 5] assert Enum.to_list(Stream.take_while(1..1000, &(&1 <= 0))) == [] assert Enum.to_list(Stream.take_while(1..3, &(&1 <= 5))) == [1, 2, 3] nats = Stream.iterate(1, &(&1 + 1)) assert Enum.to_list(Stream.take_while(nats, &(&1 <= 5))) == [1, 2, 3, 4, 5] stream = Stream.drop(1..100, 5) assert Stream.take_while(stream, &(&1 < 11)) |> Enum.to_list == [6, 7, 8, 9, 10] end test "timer/1" do stream = Stream.timer(10) now = :os.timestamp assert Enum.to_list(stream) == [0] assert :timer.now_diff(:os.timestamp, now) > 10000 end test "unfold/2" do stream = Stream.unfold(10, fn x -> if x > 0, do: {x, x-1}, else: nil end) assert Enum.take(stream, 5) == [10, 9, 8, 7, 6] stream = Stream.unfold(5, fn x -> if x > 0, do: {x, x-1}, else: nil end) assert Enum.to_list(stream) == [5, 4, 3, 2, 1] end test "unfold/2 only calculates values if needed" do stream = Stream.unfold(1, fn x -> if x > 0, do: {x, x-1}, else: throw(:boom) end) assert Enum.take(stream, 1) == [1] stream = Stream.unfold(5, fn x -> if x > 0, do: {x, x-1}, else: nil end) assert Enum.to_list(Stream.take(stream, 2)) == [5, 4] end test "unfold/2 is zippable" do stream = Stream.unfold(10, fn x -> if x > 0, do: {x, x-1}, else: nil end) list = Enum.to_list(stream) assert Enum.zip(list, list) == Enum.zip(stream, stream) end test "uniq/1" do assert Stream.uniq([1, 2, 3, 2, 1]) |> Enum.to_list == [1, 2, 3] assert Stream.uniq([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end) |> Enum.to_list == [{1, :x}, {2, :y}] end test "zip/2" do concat = Stream.concat(1..3, 4..6) cycle = Stream.cycle([:a, :b, :c]) assert Stream.zip(concat, cycle) |> Enum.to_list == [{1, :a}, {2, :b}, {3, :c}, {4, :a}, {5, :b}, {6, :c}] end test "zip/2 does not leave streams suspended" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_zip, true) end) Process.put(:stream_zip, false) assert Stream.zip([:a, :b, :c], stream) |> Enum.to_list == [a: 1, b: 2, c: 3] assert Process.get(:stream_zip) Process.put(:stream_zip, false) assert Stream.zip(stream, [:a, :b, :c]) |> Enum.to_list == [{1, :a}, {2, :b}, {3, :c}] assert Process.get(:stream_zip) end test "zip/2 does not leave streams suspended on halt" do stream = Stream.resource(fn -> 1 end, fn acc -> {[acc], acc + 1} end, fn _ -> Process.put(:stream_zip, :done) end) assert Stream.zip([:a, :b, :c, :d, :e], stream) |> Enum.take(3) == [a: 1, b: 2, c: 3] assert Process.get(:stream_zip) == :done end test "zip/2 closes on inner error" do stream = Stream.into([1, 2, 3], %PDict{}) stream = Stream.zip(stream, Stream.map([:a, :b, :c], fn _ -> throw(:error) end)) Process.put(:stream_done, false) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_done) end test "zip/2 closes on outer error" do stream = Stream.into([1, 2, 3], %PDict{}) |> Stream.zip([:a, :b, :c]) |> Stream.map(fn _ -> throw(:error) end) Process.put(:stream_done, false) assert catch_throw(Enum.to_list(stream)) == :error assert Process.get(:stream_done) end test "with_index/2" do stream = Stream.with_index([1, 2, 3]) assert is_lazy(stream) assert Enum.to_list(stream) == [{1, 0}, {2, 1}, {3, 2}] nats = Stream.iterate(1, &(&1 + 1)) assert Stream.with_index(nats) |> Enum.take(3) == [{1, 0}, {2, 1}, {3, 2}] end defp is_lazy(stream) do match?(%Stream{}, stream) or is_function(stream, 2) end defp inbox_stream({:suspend, acc}, f) do {:suspended, acc, &inbox_stream(&1, f)} end defp inbox_stream({:halt, acc}, _f) do {:halted, acc} end defp inbox_stream({:cont, acc}, f) do receive do {:stream, item} -> inbox_stream(f.(item, acc), f) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/string/000077500000000000000000000000001254730255300227405ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/string/chars_test.exs000066400000000000000000000053031254730255300256210ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule String.Chars.AtomTest do use ExUnit.Case, async: true test :basic do assert to_string(:foo) == "foo" end test :empty do assert to_string(:"") == "" end test :true_false_nil do assert to_string(false) == "false" assert to_string(true) == "true" assert to_string(nil) == "" end test :with_uppercase do assert to_string(:fOO) == "fOO" assert to_string(:FOO) == "FOO" end test :alias_atom do assert to_string(Foo.Bar) == "Elixir.Foo.Bar" end end defmodule String.Chars.BitStringTest do use ExUnit.Case, async: true test :binary do assert to_string("foo") == "foo" assert to_string(<>) == "abc" assert to_string("我今天要学习.") == "我今天要学习." end end defmodule String.Chars.NumberTest do use ExUnit.Case, async: true test :integer do assert to_string(100) == "100" end test :float do assert to_string(1.0) == "1.0" assert to_string(1.0e10) == "1.0e10" end end defmodule String.Chars.ListTest do use ExUnit.Case, async: true test :basic do assert to_string([ 1, "b", 3 ]) == <<1, 98, 3>> end test :printable do assert to_string('abc') == "abc" end test :char_list do assert to_string([0, 1, 2, 3, 255]) == <<0, 1, 2, 3, 195, 191>> assert to_string([0, [1, "hello"], 2, [["bye"]]]) == <<0, 1, 104, 101, 108, 108, 111, 2, 98, 121, 101>> end test :empty do assert to_string([]) == "" end end defmodule String.Chars.ErrorsTest do use ExUnit.Case, async: true test :bitstring do assert_raise Protocol.UndefinedError, "protocol String.Chars not implemented for <<0, 1::size(4)>>, " <> "cannot convert a bitstring to a string", fn -> to_string(<<1 :: size(12)-integer-signed>>) end end test :tuple do assert_raise Protocol.UndefinedError, "protocol String.Chars not implemented for {1, 2, 3}", fn -> to_string({1, 2, 3}) end end test :pid do assert_raise Protocol.UndefinedError, ~r"^protocol String\.Chars not implemented for #PID<.+?>$", fn -> to_string(self()) end end test :ref do assert_raise Protocol.UndefinedError, ~r"^protocol String\.Chars not implemented for #Reference<.+?>$", fn -> to_string(make_ref()) == "" end end test :function do assert_raise Protocol.UndefinedError, ~r"^protocol String\.Chars not implemented for #Function<.+?>$", fn -> to_string(fn -> end) end end test :port do [port|_] = Port.list assert_raise Protocol.UndefinedError, ~r"^protocol String\.Chars not implemented for #Port<.+?>$", fn -> to_string(port) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/string_io_test.exs000066400000000000000000000142111254730255300252060ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule StringIOTest do use ExUnit.Case, async: true test "open and close" do {:ok, pid} = StringIO.open("") assert StringIO.close(pid) == {:ok, {"", ""}} end test "contents" do {:ok, pid} = StringIO.open("abc") IO.write(pid, "edf") assert StringIO.contents(pid) == {"abc", "edf"} end test "flush" do {:ok, pid} = StringIO.open("") IO.write(pid, "edf") assert StringIO.flush(pid) == "edf" assert StringIO.contents(pid) == {"", ""} end ## IO module def start(string, opts \\ []) do StringIO.open(string, opts) |> elem(1) end def contents(pid) do StringIO.contents(pid) end test "IO.read :line with \\n" do pid = start("abc\n") assert IO.read(pid, :line) == "abc\n" assert IO.read(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.read :line with \\rn" do pid = start("abc\r\n") assert IO.read(pid, :line) == "abc\n" assert IO.read(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.read :line without line break" do pid = start("abc") assert IO.read(pid, :line) == "abc" assert IO.read(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.read :line with invalid utf8" do pid = start(<< 130, 227, 129, 132, 227, 129, 134 >>) assert IO.read(pid, :line) == {:error, :collect_line} assert contents(pid) == {<< 130, 227, 129, 132, 227, 129, 134 >>, ""} end test "IO.read count" do pid = start("abc") assert IO.read(pid, 2) == "ab" assert IO.read(pid, 8) == "c" assert IO.read(pid, 1) == :eof assert contents(pid) == {"", ""} end test "IO.read count with utf8" do pid = start("あいう") assert IO.read(pid, 2) == "あい" assert IO.read(pid, 8) == "う" assert IO.read(pid, 1) == :eof assert contents(pid) == {"", ""} end test "IO.read count with invalid utf8" do pid = start(<< 130, 227, 129, 132, 227, 129, 134 >>) assert IO.read(pid, 2) == {:error, :invalid_unicode} assert contents(pid) == {<< 130, 227, 129, 132, 227, 129, 134 >>, ""} end test "IO.binread :line with \\n" do pid = start("abc\n") assert IO.binread(pid, :line) == "abc\n" assert IO.binread(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.binread :line with \\r\\n" do pid = start("abc\r\n") assert IO.binread(pid, :line) == "abc\n" assert IO.binread(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.binread :line without line break" do pid = start("abc") assert IO.binread(pid, :line) == "abc" assert IO.binread(pid, :line) == :eof assert contents(pid) == {"", ""} end test "IO.binread count" do pid = start("abc") assert IO.binread(pid, 2) == "ab" assert IO.binread(pid, 8) == "c" assert IO.binread(pid, 1) == :eof assert contents(pid) == {"", ""} end test "IO.binread count with utf8" do pid = start("あいう") assert IO.binread(pid, 2) == << 227, 129 >> assert IO.binread(pid, 8) == << 130, 227, 129, 132, 227, 129, 134 >> assert IO.binread(pid, 1) == :eof assert contents(pid) == {"", ""} end test "IO.write" do pid = start("") assert IO.write(pid, "foo") == :ok assert contents(pid) == {"", "foo"} end test "IO.write with utf8" do pid = start("") assert IO.write(pid, "あいう") == :ok assert contents(pid) == {"", "あいう"} end test "IO.binwrite" do pid = start("") assert IO.binwrite(pid, "foo") == :ok assert contents(pid) == {"", "foo"} end test "IO.binwrite with utf8" do pid = start("") assert IO.binwrite(pid, "あいう") == :ok assert contents(pid) == {"", "あいう"} end test "IO.puts" do pid = start("") assert IO.puts(pid, "abc") == :ok assert contents(pid) == {"", "abc\n"} end test "IO.inspect" do pid = start("") assert IO.inspect(pid, {}, []) == {} assert contents(pid) == {"", "{}\n"} end test "IO.getn" do pid = start("abc") assert IO.getn(pid, ">", 2) == "ab" assert contents(pid) == {"c", ""} end test "IO.getn with utf8" do pid = start("あいう") assert IO.getn(pid, ">", 2) == "あい" assert contents(pid) == {"う", ""} end test "IO.getn with invalid utf8" do pid = start(<< 130, 227, 129, 132, 227, 129, 134 >>) assert IO.getn(pid, ">", 2) == {:error, :invalid_unicode} assert contents(pid) == {<< 130, 227, 129, 132, 227, 129, 134 >>, ""} end test "IO.getn with capture_prompt" do pid = start("abc", capture_prompt: true) assert IO.getn(pid, ">", 2) == "ab" assert contents(pid) == {"c", ">"} end test "IO.gets with \\n" do pid = start("abc\nd") assert IO.gets(pid, ">") == "abc\n" assert contents(pid) == {"d", ""} end test "IO.gets with \\r\\n" do pid = start("abc\r\nd") assert IO.gets(pid, ">") == "abc\n" assert contents(pid) == {"d", ""} end test "IO.gets without line breaks" do pid = start("abc") assert IO.gets(pid, ">") == "abc" assert contents(pid) == {"", ""} end test "IO.gets with invalid utf8" do pid = start(<< 130, 227, 129, 132, 227, 129, 134 >>) assert IO.gets(pid, ">") == {:error, :collect_line} assert contents(pid) == {<< 130, 227, 129, 132, 227, 129, 134 >>, ""} end test "IO.gets with capture_prompt" do pid = start("abc\n", capture_prompt: true) assert IO.gets(pid, ">") == "abc\n" assert contents(pid) == {"", ">"} end test ":io.get_password" do pid = start("abc\n") assert :io.get_password(pid) == "abc\n" assert contents(pid) == {"", ""} end test "IO.stream" do pid = start("abc") assert IO.stream(pid, 2) |> Enum.to_list == ["ab", "c"] assert contents(pid) == {"", ""} end test "IO.stream with invalid utf8" do pid = start(<< 130, 227, 129, 132, 227, 129, 134 >>) assert_raise IO.StreamError, fn-> IO.stream(pid, 2) |> Enum.to_list end assert contents(pid) == {<< 130, 227, 129, 132, 227, 129, 134 >>, ""} end test "IO.binstream" do pid = start("abc") assert IO.stream(pid, 2) |> Enum.to_list == ["ab", "c"] assert contents(pid) == {"", ""} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/string_test.exs000066400000000000000000000540611254730255300245260ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule StringTest do use ExUnit.Case, async: true test :next_codepoint do assert String.next_codepoint("ésoj") == {"é", "soj"} assert String.next_codepoint(<<255>>) == {<<255>>, ""} assert String.next_codepoint("") == nil end # test cases described in http://mortoray.com/2013/11/27/the-string-type-is-broken/ test :unicode do assert String.reverse("noël") == "lëon" assert String.slice("noël", 0..2) == "noë" assert String.length("noël") == 4 assert String.length("") == 2 assert String.slice("", 1..1) == "" assert String.reverse("") == "" assert String.upcase("baffle") == "BAFFLE" end test :split do assert String.split("") == [] assert String.split("foo bar") == ["foo", "bar"] assert String.split(" foo bar") == ["foo", "bar"] assert String.split("foo bar ") == ["foo", "bar"] assert String.split(" foo bar ") == ["foo", "bar"] assert String.split("foo\t\n\v\f\r\sbar\n") == ["foo", "bar"] assert String.split("foo" <> <<31>> <> "bar") == ["foo", "bar"] assert String.split("foo" <> <<194, 133>> <> "bar") == ["foo", "bar"] assert String.split("a,b,c", ",") == ["a", "b", "c"] assert String.split("a,b", ".") == ["a,b"] assert String.split("1,2 3,4", [" ", ","]) == ["1", "2", "3", "4"] assert String.split("", ",") == [""] assert String.split(" a b c ", " ") == ["", "a", "b", "c", ""] assert String.split(" a b c ", " ", parts: :infinity) == ["", "a", "b", "c", ""] assert String.split(" a b c ", " ", parts: 1) == [" a b c "] assert String.split(" a b c ", " ", parts: 2) == ["", "a b c "] assert String.split("", ",", trim: true) == [] assert String.split(" a b c ", " ", trim: true) == ["a", "b", "c"] assert String.split(" a b c ", " ", trim: true, parts: :infinity) == ["a", "b", "c"] assert String.split(" a b c ", " ", trim: true, parts: 1) == [" a b c "] assert String.split(" a b c ", " ", trim: true, parts: 2) == ["a", "b c "] assert String.split("abé", "") == ["a", "b", "é", ""] assert String.split("abé", "", parts: :infinity) == ["a", "b", "é", ""] assert String.split("abé", "", parts: 1) == ["abé"] assert String.split("abé", "", parts: 2) == ["a", "bé"] assert String.split("abé", "", parts: 10) == ["a", "b", "é", ""] assert String.split("abé", "", trim: true) == ["a", "b", "é"] assert String.split("abé", "", trim: true, parts: :infinity) == ["a", "b", "é"] assert String.split("abé", "", trim: true, parts: 2) == ["a", "bé"] assert String.split("noël", "") == ["n", "o", "ë", "l", ""] end test :split_with_regex do assert String.split("", ~r{,}) == [""] assert String.split("", ~r{,}, trim: true) == [] assert String.split("a,b", ~r{,}) == ["a", "b"] assert String.split("a,b,c", ~r{,}) == ["a", "b", "c"] assert String.split("a,b,c", ~r{,}, parts: 2) == ["a", "b,c"] assert String.split("a,b.c ", ~r{\W}) == ["a", "b", "c", ""] assert String.split("a,b.c ", ~r{\W}, trim: false) == ["a", "b", "c", ""] assert String.split("a,b", ~r{\.}) == ["a,b"] end test :splitter do assert String.splitter("a,b,c", ",") |> Enum.to_list == ["a", "b", "c"] assert String.splitter("a,b", ".") |> Enum.to_list == ["a,b"] assert String.splitter("1,2 3,4", [" ", ","]) |> Enum.to_list == ["1", "2", "3", "4"] assert String.splitter("", ",") |> Enum.to_list == [""] assert String.splitter("", ",", trim: true) |> Enum.to_list == [] assert String.splitter(" a b c ", " ", trim: true) |> Enum.to_list == ["a", "b", "c"] assert String.splitter(" a b c ", " ", trim: true) |> Enum.take(1) == ["a"] assert String.splitter(" a b c ", " ", trim: true) |> Enum.take(2) == ["a", "b"] end test :split_at do assert String.split_at("", 0) == {"", ""} assert String.split_at("", -1) == {"", ""} assert String.split_at("", 1) == {"", ""} assert String.split_at("abc", 0) == {"", "abc"} assert String.split_at("abc", 2) == {"ab", "c"} assert String.split_at("abc", 3) == {"abc", ""} assert String.split_at("abc", 4) == {"abc", ""} assert String.split_at("abc", 1000) == {"abc", ""} assert String.split_at("abc", -1) == {"ab", "c"} assert String.split_at("abc", -3) == {"", "abc"} assert String.split_at("abc", -4) == {"", "abc"} assert String.split_at("abc", -1000) == {"", "abc"} assert_raise FunctionClauseError, fn -> String.split_at("abc", 0.1) end assert_raise FunctionClauseError, fn -> String.split_at("abc", -0.1) end end test :upcase do assert String.upcase("123 abcd 456 efg hij ( %$#) kl mnop @ qrst = -_ uvwxyz") == "123 ABCD 456 EFG HIJ ( %$#) KL MNOP @ QRST = -_ UVWXYZ" assert String.upcase("") == "" assert String.upcase("abcD") == "ABCD" end test :upcase_utf8 do assert String.upcase("& % # àáâ ãäå 1 2 ç æ") == "& % # ÀÁ ÃÄÅ 1 2 Ç Æ" assert String.upcase("àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ") == "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ" end test :upcase_utf8_multibyte do assert String.upcase("straße") == "STRASSE" assert String.upcase("áüÈß") == "ÁÜÈSS" end test :downcase do assert String.downcase("123 ABcD 456 EfG HIJ ( %$#) KL MNOP @ QRST = -_ UVWXYZ") == "123 abcd 456 efg hij ( %$#) kl mnop @ qrst = -_ uvwxyz" assert String.downcase("abcD") == "abcd" assert String.downcase("") == "" end test :downcase_utf8 do assert String.downcase("& % # ÀÁ ÃÄÅ 1 2 Ç Æ") == "& % # àáâ ãäå 1 2 ç æ" assert String.downcase("ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ") == "àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ" assert String.downcase("áüÈß") == "áüèß" end test :capitalize do assert String.capitalize("") == "" assert String.capitalize("abc") == "Abc" assert String.capitalize("ABC") == "Abc" assert String.capitalize("c b a") == "C b a" assert String.capitalize("1ABC") == "1abc" assert String.capitalize("_aBc1") == "_abc1" assert String.capitalize(" aBc1") == " abc1" end test :capitalize_utf8 do assert String.capitalize("àáâ") == "Àáâ" assert String.capitalize("ÀÁÂ") == "Àáâ" assert String.capitalize("âáà") == "Âáà" assert String.capitalize("ÂÁÀ") == "Âáà" assert String.capitalize("òóôõö") == "Òóôõö" assert String.capitalize("ÒÓÔÕÖ") == "Òóôõö" assert String.capitalize("fin") == "Fin" end test :rstrip do assert String.rstrip("") == "" assert String.rstrip("1\n") == "1" assert String.rstrip("\r\n") == "" assert String.rstrip(" abc ") == " abc" assert String.rstrip(" abc a") == " abc a" assert String.rstrip("a abc a\n\n") == "a abc a" assert String.rstrip("a abc a\t\n\v\f\r\s") == "a abc a" assert String.rstrip("a abc a " <> <<31>>) == "a abc a" assert String.rstrip("a abc a" <> <<194, 133>>) == "a abc a" assert String.rstrip(" abc aa", ?a) == " abc " assert String.rstrip(" abc __", ?_) == " abc " assert String.rstrip(" cat 猫猫", ?猫) == " cat " end test :lstrip do assert String.lstrip("") == "" assert String.lstrip(" abc ") == "abc " assert String.lstrip("a abc a") == "a abc a" assert String.lstrip("\n\na abc a") == "a abc a" assert String.lstrip("\t\n\v\f\r\sa abc a") == "a abc a" assert String.lstrip(<<31>> <> " a abc a") == "a abc a" assert String.lstrip(<<194, 133>> <> "a abc a") == "a abc a" assert String.lstrip("__ abc _", ?_) == " abc _" assert String.lstrip("猫猫 cat ", ?猫) == " cat " end test :strip do assert String.strip("") == "" assert String.strip(" abc ") == "abc" assert String.strip("a abc a\n\n") == "a abc a" assert String.strip("a abc a\t\n\v\f\r\s") == "a abc a" assert String.strip("___ abc ___", ?_) == " abc " assert String.strip("猫猫猫 cat 猫猫猫", ?猫) == " cat " end test :rjust do assert String.rjust("", 5) == " " assert String.rjust("abc", 5) == " abc" assert String.rjust(" abc ", 9) == " abc " assert String.rjust("猫", 5) == " 猫" assert String.rjust("abc", 5, ?-) == "--abc" assert String.rjust("abc", 5, ?猫) == "猫猫abc" assert String.rjust("-", 0) == "-" assert_raise FunctionClauseError, fn -> String.rjust("-", -1) end end test :ljust do assert String.ljust("", 5) == " " assert String.ljust("abc", 5) == "abc " assert String.ljust(" abc ", 9) == " abc " assert String.ljust("猫", 5) == "猫 " assert String.ljust("abc", 5, ?-) == "abc--" assert String.ljust("abc", 5, ?猫) == "abc猫猫" assert String.ljust("-", 0) == "-" assert_raise FunctionClauseError, fn -> String.ljust("-", -1) end end test :reverse do assert String.reverse("") == "" assert String.reverse("abc") == "cba" assert String.reverse("Hello World") == "dlroW olleH" assert String.reverse("Hello ∂og") == "go∂ olleH" assert String.reverse("Ā̀stute") == "etutsĀ̀" assert String.reverse(String.reverse("Hello World")) == "Hello World" assert String.reverse(String.reverse("Hello \r\n World")) == "Hello \r\n World" end test :replace do assert String.replace("a,b,c", ",", "-") == "a-b-c" assert String.replace("a,b,c", [",", "b"], "-") == "a---c" assert String.replace("a,b,c", ",", "-", global: false) == "a-b,c" assert String.replace("a,b,c", [",", "b"], "-", global: false) == "a-b,c" assert String.replace("ãéã", "é", "e", global: false) == "ãeã" assert String.replace("a,b,c", ",", "[]", insert_replaced: 2) == "a[],b[],c" assert String.replace("a,b,c", ",", "[]", insert_replaced: [1, 1]) == "a[,,]b[,,]c" assert String.replace("a,b,c", "b", "[]", insert_replaced: 1, global: false) == "a,[b],c" assert String.replace("a,b,c", ~r/,(.)/, ",\\1\\1") == "a,bb,cc" assert String.replace("a,b,c", ~r/,(.)/, ",\\1\\1", global: false) == "a,bb,c" end test :duplicate do assert String.duplicate("abc", 0) == "" assert String.duplicate("abc", 1) == "abc" assert String.duplicate("abc", 2) == "abcabc" assert String.duplicate("&ã$", 2) == "&ã$&ã$" assert_raise FunctionClauseError, fn -> String.duplicate("abc", -1) end end test :codepoints do assert String.codepoints("elixir") == ["e", "l", "i", "x", "i", "r"] assert String.codepoints("elixír") == ["e", "l", "i", "x", "í", "r"] # slovak assert String.codepoints("ոգելից ըմպելիք") == ["ո", "գ", "ե", "լ", "ի", "ց", " ", "ը", "մ", "պ", "ե", "լ", "ի", "ք"] # armenian assert String.codepoints("эліксір") == ["э", "л", "і", "к", "с", "і", "р"] # belarussian assert String.codepoints("ελιξήριο") == ["ε", "λ", "ι", "ξ", "ή", "ρ", "ι", "ο"] # greek assert String.codepoints("סם חיים") == ["ס", "ם", " ", "ח", "י", "י", "ם"] # hebraic assert String.codepoints("अमृत") == ["अ", "म", "ृ", "त"] # hindi assert String.codepoints("স্পর্শমণি") == ["স", "্", "প", "র", "্", "শ", "ম", "ণ", "ি"] # bengali assert String.codepoints("સર્વશ્રેષ્ઠ ઇલાજ") == ["સ", "ર", "્", "વ", "શ", "્", "ર", "ે", "ષ", "્", "ઠ", " ", "ઇ", "લ", "ા", "જ"] # gujarati assert String.codepoints("世界中の一番") == ["世", "界", "中", "の", "一", "番"] # japanese assert String.codepoints("がガちゃ") == ["が", "ガ", "ち", "ゃ"] assert String.codepoints("") == [] assert String.codepoints("ϖͲϥЫݎߟΈټϘለДШव׆ש؇؊صلټܗݎޥޘ߉ऌ૫ሏᶆ℆ℙℱ ⅚Ⅷ↠∈⌘①ffi") == ["ϖ", "Ͳ", "ϥ", "Ы", "ݎ", "ߟ", "Έ", "ټ", "Ϙ", "ለ", "Д", "Ш", "व", "׆", "ש", "؇", "؊", "ص", "ل", "ټ", "ܗ", "ݎ", "ޥ", "ޘ", "߉", "ऌ", "૫", "ሏ", "ᶆ", "℆", "ℙ", "ℱ", " ", "⅚", "Ⅷ", "↠", "∈", "⌘", "①", "ffi"] end test :graphemes do # Extended assert String.graphemes("Ā̀stute") == ["Ā̀", "s", "t", "u", "t", "e"] # CLRF assert String.graphemes("\r\n\f") == ["\r\n", "\f"] # Regional indicator assert String.graphemes("\x{1F1E6}\x{1F1E7}\x{1F1E8}") == ["\x{1F1E6}\x{1F1E7}\x{1F1E8}"] # Hangul assert String.graphemes("\x{1100}\x{115D}\x{B4A4}") == ["ᄀᅝ뒤"] # Special Marking with Extended assert String.graphemes("a\x{0300}\x{0903}") == ["a\x{0300}\x{0903}"] end test :next_grapheme do assert String.next_grapheme("Ā̀stute") == {"Ā̀", "stute"} assert String.next_grapheme("") == nil end test :first do assert String.first("elixir") == "e" assert String.first("íelixr") == "í" assert String.first("եոգլից ըմպելիք") == "ե" assert String.first("лэіксір") == "л" assert String.first("ελιξήριο") == "ε" assert String.first("סם חיים") == "ס" assert String.first("がガちゃ") == "が" assert String.first("Ā̀stute") == "Ā̀" assert String.first("") == nil end test :last do assert String.last("elixir") == "r" assert String.last("elixrí") == "í" assert String.last("եոգլից ըմպելիքե") == "ե" assert String.last("ліксірэ") == "э" assert String.last("ειξήριολ") == "λ" assert String.last("סם ייםח") == "ח" assert String.last("がガちゃ") == "ゃ" assert String.last("Ā̀") == "Ā̀" assert String.last("") == nil end test :length do assert String.length("elixir") == 6 assert String.length("elixrí") == 6 assert String.length("եոգլից") == 6 assert String.length("ліксрэ") == 6 assert String.length("ειξήριολ") == 8 assert String.length("סם ייםח") == 7 assert String.length("がガちゃ") == 4 assert String.length("Ā̀stute") == 6 assert String.length("") == 0 end test :at do assert String.at("л", 0) == "л" assert String.at("elixir", 1) == "l" assert String.at("がガちゃ", 2) == "ち" assert String.at("л", 10) == nil assert String.at("elixir", -1) == "r" assert String.at("がガちゃ", -2) == "ち" assert String.at("л", -3) == nil assert String.at("Ā̀stute", 1) == "s" assert String.at("elixir", 6) == nil assert_raise FunctionClauseError, fn -> String.at("elixir", 0.1) end assert_raise FunctionClauseError, fn -> String.at("elixir", -0.1) end end test :slice do assert String.slice("elixir", 1, 3) == "lix" assert String.slice("あいうえお", 2, 2) == "うえ" assert String.slice("ειξήριολ", 2, 3) == "ξήρ" assert String.slice("elixir", 3, 4) == "xir" assert String.slice("あいうえお", 3, 5) == "えお" assert String.slice("ειξήριολ", 5, 4) == "ιολ" assert String.slice("elixir", -3, 2) == "xi" assert String.slice("あいうえお", -4, 3) == "いうえ" assert String.slice("ειξήριολ", -5, 3) == "ήρι" assert String.slice("elixir", -10, 1) == "" assert String.slice("あいうえお", -10, 2) == "" assert String.slice("ειξήριολ", -10, 3) == "" assert String.slice("elixir", 8, 2) == "" assert String.slice("あいうえお", 6, 2) == "" assert String.slice("ειξήριολ", 8, 1) == "" assert String.slice("ειξήριολ", 9, 1) == "" assert String.slice("elixir", 0, 0) == "" assert String.slice("elixir", 5, 0) == "" assert String.slice("elixir", -5, 0) == "" assert String.slice("", 0, 1) == "" assert String.slice("", 1, 1) == "" assert String.slice("elixir", 0..-2) == "elixi" assert String.slice("elixir", 1..3) == "lix" assert String.slice("elixir", -5..-3) == "lix" assert String.slice("elixir", -5..3) == "lix" assert String.slice("あいうえお", 2..3) == "うえ" assert String.slice("ειξήριολ", 2..4) == "ξήρ" assert String.slice("elixir", 3..6) == "xir" assert String.slice("あいうえお", 3..7) == "えお" assert String.slice("ειξήριολ", 5..8) == "ιολ" assert String.slice("elixir", -3..-2) == "xi" assert String.slice("あいうえお", -4..-2) == "いうえ" assert String.slice("ειξήριολ", -5..-3) == "ήρι" assert String.slice("elixir", 8..9) == "" assert String.slice("あいうえお", 6..7) == "" assert String.slice("ειξήριολ", 8..8) == "" assert String.slice("ειξήριολ", 9..9) == "" assert String.slice("", 0..0) == "" assert String.slice("", 1..1) == "" assert String.slice("あいうえお", -2..-4) == "" assert String.slice("あいうえお", -10..-15) == "" assert String.slice("hello あいうえお unicode", 8..-1) == "うえお unicode" assert String.slice("abc", -1..14) == "c" end test :valid? do assert String.valid?("afds") assert String.valid?("øsdfh") assert String.valid?("dskfjあska") refute String.valid?(<<0xffff :: 16>>) refute String.valid?("asd" <> <<0xffff :: 16>>) end test :valid_character? do assert String.valid_character?("a") assert String.valid_character?("ø") assert String.valid_character?("あ") refute String.valid_character?("\x{ffff}") refute String.valid_character?("ab") end test :chunk_valid do assert String.chunk("", :valid) == [] assert String.chunk("ødskfjあ\x11ska", :valid) == ["ødskfjあ\x11ska"] assert String.chunk("abc\x{0ffff}def", :valid) == ["abc", <<0x0ffff::utf8>>, "def"] assert String.chunk("\x{0fffe}\x{3ffff}привет\x{0ffff}мир", :valid) == [<<0x0fffe::utf8, 0x3ffff::utf8>>, "привет", <<0x0ffff::utf8>>, "мир"] assert String.chunk("日本\x{0ffff}\x{fdef}ござございます\x{fdd0}", :valid) == ["日本", <<0x0ffff::utf8, 0xfdef::utf8>>, "ござございます", <<0xfdd0::utf8>>] end test :chunk_printable do assert String.chunk("", :printable) == [] assert String.chunk("ødskfjあska", :printable) == ["ødskfjあska"] assert String.chunk("abc\x{0ffff}def", :printable) == ["abc", <<0x0ffff::utf8>>, "def"] assert String.chunk("\x06ab\x05cdef\x03\0", :printable) == [<<6>>, "ab", <<5>>, "cdef", <<3, 0>>] end test :starts_with? do assert String.starts_with? "hello", "he" assert String.starts_with? "hello", "hello" refute String.starts_with? "hello", [] assert String.starts_with? "hello", ["hellö", "hell"] assert String.starts_with? "エリクシア", "エリ" refute String.starts_with? "hello", "lo" refute String.starts_with? "hello", "hellö" refute String.starts_with? "hello", ["hellö", "goodbye"] refute String.starts_with? "エリクシア", "仙丹" end test :ends_with? do assert String.ends_with? "hello", "lo" assert String.ends_with? "hello", "hello" refute String.ends_with? "hello", [] assert String.ends_with? "hello", ["hell", "lo", "xx"] assert String.ends_with? "hello", ["hellö", "lo"] assert String.ends_with? "エリクシア", "シア" refute String.ends_with? "hello", "he" refute String.ends_with? "hello", "hellö" refute String.ends_with? "hello", ["hel", "goodbye"] refute String.ends_with? "エリクシア", "仙丹" end test :contains? do assert String.contains? "elixir of life", "of" assert String.contains? "エリクシア", "シ" refute String.contains? "elixir of life", [] assert String.contains? "elixir of life", ["mercury", "life"] refute String.contains? "elixir of life", "death" refute String.contains? "エリクシア", "仙" refute String.contains? "elixir of life", ["death", "mercury", "eternal life"] end test :to_char_list do assert String.to_char_list("æß") == [?æ, ?ß] assert String.to_char_list("abc") == [?a, ?b, ?c] assert_raise UnicodeConversionError, "invalid encoding starting at <<223, 255>>", fn -> String.to_char_list(<< 0xDF, 0xFF >>) end assert_raise UnicodeConversionError, "incomplete encoding starting at <<195>>", fn -> String.to_char_list(<< 106, 111, 115, 195 >>) end end test :to_float do assert String.to_float("3.0") == 3.0 three = fn -> "3" end assert_raise ArgumentError, fn -> String.to_float(three.()) end end test :jaro_distance do assert String.jaro_distance("same", "same") == 1.0 assert String.jaro_distance("any", "") == 0.0 assert String.jaro_distance("", "any") == 0.0 assert String.jaro_distance("martha", "marhta") == 0.9444444444444445 assert String.jaro_distance("martha", "marhha") == 0.888888888888889 assert String.jaro_distance("marhha", "martha") == 0.888888888888889 assert String.jaro_distance("dwayne", "duane") == 0.8222222222222223 assert String.jaro_distance("dixon", "dicksonx") == 0.7666666666666666 assert String.jaro_distance("xdicksonx", "dixon") == 0.7851851851851852 assert String.jaro_distance("shackleford", "shackelford") == 0.9696969696969697 assert String.jaro_distance("dunningham", "cunnigham") == 0.8962962962962964 assert String.jaro_distance("nichleson", "nichulson") == 0.9259259259259259 assert String.jaro_distance("jones", "johnson") == 0.7904761904761904 assert String.jaro_distance("massey", "massie") == 0.888888888888889 assert String.jaro_distance("abroms", "abrams") == 0.888888888888889 assert String.jaro_distance("hardin", "martinez") == 0.7222222222222222 assert String.jaro_distance("itman", "smith") == 0.4666666666666666 assert String.jaro_distance("jeraldine", "geraldine") == 0.9259259259259259 assert String.jaro_distance("michelle", "michael") == 0.8690476190476191 assert String.jaro_distance("julies", "julius") == 0.888888888888889 assert String.jaro_distance("tanya", "tonya") == 0.8666666666666667 assert String.jaro_distance("sean", "susan") == 0.7833333333333333 assert String.jaro_distance("jon", "john") == 0.9166666666666666 assert String.jaro_distance("jon", "jan") == 0.7777777777777777 end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/supervisor/000077500000000000000000000000001254730255300236535ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/supervisor/spec_test.exs000066400000000000000000000034761254730255300263770ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Supervisor.SpecTest do use ExUnit.Case, async: true import Supervisor.Spec test "worker/3" do assert worker(Foo, [1, 2, 3]) == { Foo, {Foo, :start_link, [1, 2, 3]}, :permanent, 5000, :worker, [Foo] } opts = [id: :sample, function: :start, modules: :dynamic, restart: :temporary, shutdown: :brutal_kill] assert worker(Foo, [1, 2, 3], opts) == { :sample, {Foo, :start, [1, 2, 3]}, :temporary, :brutal_kill, :worker, :dynamic } end test "worker/3 with GenEvent" do assert worker(GenEvent, [[name: :hello]]) == { GenEvent, {GenEvent, :start_link, [[name: :hello]]}, :permanent, 5000, :worker, :dynamic } end test "supervisor/3" do assert supervisor(Foo, [1, 2, 3]) == { Foo, {Foo, :start_link, [1, 2, 3]}, :permanent, :infinity, :supervisor, [Foo] } opts = [id: :sample, function: :start, modules: :dynamic, restart: :temporary, shutdown: :brutal_kill] assert supervisor(Foo, [1, 2, 3], opts) == { :sample, {Foo, :start, [1, 2, 3]}, :temporary, :brutal_kill, :supervisor, :dynamic } end test "supervise/2" do assert supervise([], strategy: :one_for_one) == { :ok, {{:one_for_one, 3, 5}, []} } children = [worker(GenEvent, [])] options = [strategy: :one_for_all, max_restarts: 1, max_seconds: 1] assert supervise(children, options) == { :ok, {{:one_for_all, 1, 1}, children} } end test "supervise/2 with duplicated ids" do children = [worker(GenEvent, []), worker(GenEvent, [])] assert_raise ArgumentError, fn -> supervise(children, strategy: :one_for_one) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/supervisor_test.exs000066400000000000000000000053041254730255300254350ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule SupervisorTest do use ExUnit.Case, async: true defmodule Stack do use GenServer def start_link(state, opts) do GenServer.start_link(__MODULE__, state, opts) end def handle_call(:pop, _from, [h|t]) do {:reply, h, t} end def handle_call(:stop, _from, stack) do # There is a race condition between genserver terminations. # So we will explicitly unregister it here. try do self |> Process.info(:registered_name) |> elem(1) |> Process.unregister rescue _ -> :ok end {:stop, :normal, :ok, stack} end def handle_cast({:push, h}, t) do {:noreply, [h|t]} end end defmodule Stack.Sup do use Supervisor def init({arg, opts}) do children = [worker(Stack, [arg, opts])] supervise(children, strategy: :one_for_one) end end import Supervisor.Spec test "start_link/2" do children = [worker(Stack, [[:hello], [name: :dyn_stack]])] {:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one) wait_until_registered(:dyn_stack) assert GenServer.call(:dyn_stack, :pop) == :hello assert GenServer.call(:dyn_stack, :stop) == :ok wait_until_registered(:dyn_stack) assert GenServer.call(:dyn_stack, :pop) == :hello Process.exit(pid, :normal) end test "start_link/3" do {:ok, pid} = Supervisor.start_link(Stack.Sup, {[:hello], [name: :stat_stack]}, name: :stack_sup) wait_until_registered(:stack_sup) assert GenServer.call(:stat_stack, :pop) == :hello Process.exit(pid, :normal) end test "*_child functions" do {:ok, pid} = Supervisor.start_link([], strategy: :one_for_one) assert Supervisor.which_children(pid) == [] assert Supervisor.count_children(pid) == %{specs: 0, active: 0, supervisors: 0, workers: 0} {:ok, stack} = Supervisor.start_child(pid, worker(Stack, [[:hello], []])) assert GenServer.call(stack, :pop) == :hello assert Supervisor.which_children(pid) == [{SupervisorTest.Stack, stack, :worker, [SupervisorTest.Stack]}] assert Supervisor.count_children(pid) == %{specs: 1, active: 1, supervisors: 0, workers: 1} assert Supervisor.delete_child(pid, Stack) == {:error, :running} assert Supervisor.terminate_child(pid, Stack) == :ok {:ok, stack} = Supervisor.restart_child(pid, Stack) assert GenServer.call(stack, :pop) == :hello assert Supervisor.terminate_child(pid, Stack) == :ok assert Supervisor.delete_child(pid, Stack) == :ok Process.exit(pid, :normal) end defp wait_until_registered(name) do unless Process.whereis(name) do wait_until_registered(name) end end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/system_test.exs000066400000000000000000000053711254730255300245440ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule SystemTest do use ExUnit.Case import PathHelpers test "build_info/0" do assert is_map System.build_info assert not is_nil(System.build_info[:version]) assert not is_nil(System.build_info[:tag]) assert not is_nil(System.build_info[:date]) end test "cwd/0" do assert is_binary System.cwd assert is_binary System.cwd! end if :file.native_name_encoding == :utf8 do test "cwd/0 with utf8" do File.mkdir_p(tmp_path("héllò")) File.cd!(tmp_path("héllò"), fn -> assert Path.basename(System.cwd!) == "héllò" end) after File.rm_rf tmp_path("héllò") end end test "user_home/0" do assert is_binary System.user_home assert is_binary System.user_home! end test "tmp_dir/0" do assert is_binary System.tmp_dir assert is_binary System.tmp_dir! end test "argv/0" do list = elixir('-e "IO.inspect System.argv" -- -o opt arg1 arg2 --long-opt 10') {args, _} = Code.eval_string list, [] assert args == ["-o", "opt", "arg1", "arg2", "--long-opt", "10"] end @test_var "SYSTEM_ELIXIR_ENV_TEST_VAR" test "*_env/*" do assert System.get_env(@test_var) == nil System.put_env(@test_var, "SAMPLE") assert System.get_env(@test_var) == "SAMPLE" assert System.get_env()[@test_var] == "SAMPLE" System.delete_env(@test_var) assert System.get_env(@test_var) == nil System.put_env(%{@test_var => "OTHER_SAMPLE"}) assert System.get_env(@test_var) == "OTHER_SAMPLE" end test "cmd/2" do assert {"hello\n", 0} = System.cmd "echo", ["hello"] end test "cmd/3 (with options)" do assert {["hello\n"], 0} = System.cmd "echo", ["hello"], into: [], cd: System.cwd!, env: %{"foo" => "bar"}, arg0: "echo", stderr_to_stdout: true, parallelism: true end @echo "echo-elixir-test" test "cmd/2 with absolute and relative paths" do echo = tmp_path(@echo) File.mkdir_p! Path.dirname(echo) File.cp! System.find_executable("echo"), echo File.cd! Path.dirname(echo), fn -> # There is a bug in OTP where find_executable is finding # entries on the current directory. If this is the case, # we should avoid the assertion below. unless System.find_executable(@echo) do assert :enoent = catch_error(System.cmd(@echo, ["hello"])) end assert {"hello\n", 0} = System.cmd(Path.join(System.cwd!, @echo), ["hello"], [{:arg0, "echo"}]) end after File.rm_rf! tmp_path(@echo) end test "find_executable/1" do assert System.find_executable("erl") assert is_binary System.find_executable("erl") assert !System.find_executable("does-not-really-exist-from-elixir") end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/task/000077500000000000000000000000001254730255300223745ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/task/supervisor_test.exs000066400000000000000000000075661254730255300264130ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Task.SupervisorTest do use ExUnit.Case setup do {:ok, pid} = Task.Supervisor.start_link() {:ok, supervisor: pid} end setup do Logger.remove_backend(:console) on_exit fn -> Logger.add_backend(:console, flush: true) end :ok end def wait_and_send(caller, atom) do send caller, :ready receive do: (true -> true) send caller, atom end test "async/1", config do parent = self() fun = fn -> wait_and_send(parent, :done) end task = Task.Supervisor.async(config[:supervisor], fun) assert Task.Supervisor.children(config[:supervisor]) == [task.pid] # Assert the struct assert task.__struct__ == Task assert is_pid task.pid assert is_reference task.ref # Assert the link {:links, links} = Process.info(self, :links) assert task.pid in links receive do: (:ready -> :ok) # Assert the initial call {:name, fun_name} = :erlang.fun_info(fun, :name) assert {__MODULE__, fun_name, 0} === :proc_lib.translate_initial_call(task.pid) # Run the task send task.pid, true # Assert response and monitoring messages ref = task.ref assert_receive {^ref, :done} assert_receive {:DOWN, ^ref, _, _, :normal} end test "async/3", config do task = Task.Supervisor.async(config[:supervisor], __MODULE__, :wait_and_send, [self(), :done]) assert Task.Supervisor.children(config[:supervisor]) == [task.pid] receive do: (:ready -> :ok) assert {__MODULE__, :wait_and_send, 2} === :proc_lib.translate_initial_call(task.pid) send task.pid, true assert task.__struct__ == Task assert Task.await(task) == :done end test "start_child/1", config do parent = self() fun = fn -> wait_and_send(parent, :done) end {:ok, pid} = Task.Supervisor.start_child(config[:supervisor], fun) assert Task.Supervisor.children(config[:supervisor]) == [pid] {:links, links} = Process.info(self, :links) refute pid in links receive do: (:ready -> :ok) {:name, fun_name} = :erlang.fun_info(fun, :name) assert {__MODULE__, fun_name, 0} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "start_child/3", config do {:ok, pid} = Task.Supervisor.start_child(config[:supervisor], __MODULE__, :wait_and_send, [self(), :done]) assert Task.Supervisor.children(config[:supervisor]) == [pid] {:links, links} = Process.info(self, :links) refute pid in links receive do: (:ready -> :ok) assert {__MODULE__, :wait_and_send, 2} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "terminate_child/2", config do {:ok, pid} = Task.Supervisor.start_child(config[:supervisor], __MODULE__, :wait_and_send, [self(), :done]) assert Task.Supervisor.children(config[:supervisor]) == [pid] assert Task.Supervisor.terminate_child(config[:supervisor], pid) == :ok assert Task.Supervisor.children(config[:supervisor]) == [] assert Task.Supervisor.terminate_child(config[:supervisor], pid) == :ok end test "await/1 exits on task throw", config do Process.flag(:trap_exit, true) task = Task.Supervisor.async(config[:supervisor], fn -> throw :unknown end) assert {{{:nocatch, :unknown}, _}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task error", config do Process.flag(:trap_exit, true) task = Task.Supervisor.async(config[:supervisor], fn -> raise "oops" end) assert {{%RuntimeError{}, _}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task exit", config do Process.flag(:trap_exit, true) task = Task.Supervisor.async(config[:supervisor], fn -> exit :unknown end) assert {:unknown, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/task_test.exs000066400000000000000000000122561254730255300241620ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule TaskTest do use ExUnit.Case setup do Logger.remove_backend(:console) on_exit fn -> Logger.add_backend(:console, flush: true) end :ok end def wait_and_send(caller, atom) do send caller, :ready receive do: (true -> true) send caller, atom end test "async/1" do parent = self() fun = fn -> wait_and_send(parent, :done) end task = Task.async(fun) # Assert the struct assert task.__struct__ == Task assert is_pid task.pid assert is_reference task.ref # Assert the link {:links, links} = Process.info(self, :links) assert task.pid in links receive do: (:ready -> :ok) # Assert the initial call {:name, fun_name} = :erlang.fun_info(fun, :name) assert {__MODULE__, fun_name, 0} === :proc_lib.translate_initial_call(task.pid) # Run the task send task.pid, true # Assert response and monitoring messages ref = task.ref assert_receive {^ref, :done} assert_receive {:DOWN, ^ref, _, _, :normal} end test "async/3" do task = Task.async(__MODULE__, :wait_and_send, [self(), :done]) assert task.__struct__ == Task {:links, links} = Process.info(self, :links) assert task.pid in links receive do: (:ready -> :ok) assert {__MODULE__, :wait_and_send, 2} === :proc_lib.translate_initial_call(task.pid) send(task.pid, true) assert Task.await(task) === :done assert_receive :done end test "start/1" do parent = self() fun = fn -> wait_and_send(parent, :done) end {:ok, pid} = Task.start(fun) {:links, links} = Process.info(self, :links) refute pid in links receive do: (:ready -> :ok) {:name, fun_name} = :erlang.fun_info(fun, :name) assert {__MODULE__, fun_name, 0} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "start/3" do {:ok, pid} = Task.start(__MODULE__, :wait_and_send, [self(), :done]) {:links, links} = Process.info(self, :links) refute pid in links receive do: (:ready -> :ok) assert {__MODULE__, :wait_and_send, 2} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "start_link/1" do parent = self() fun = fn -> wait_and_send(parent, :done) end {:ok, pid} = Task.start_link(fun) {:links, links} = Process.info(self, :links) assert pid in links receive do: (:ready -> :ok) {:name, fun_name} = :erlang.fun_info(fun, :name) assert {__MODULE__, fun_name, 0} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "start_link/3" do {:ok, pid} = Task.start_link(__MODULE__, :wait_and_send, [self(), :done]) {:links, links} = Process.info(self, :links) assert pid in links receive do: (:ready -> :ok) assert {__MODULE__, :wait_and_send, 2} === :proc_lib.translate_initial_call(pid) send pid, true assert_receive :done end test "await/1 exits on timeout" do task = %Task{ref: make_ref()} assert catch_exit(Task.await(task, 0)) == {:timeout, {Task, :await, [task, 0]}} end test "await/1 exits on normal exit" do task = Task.async(fn -> exit :normal end) assert catch_exit(Task.await(task)) == {:normal, {Task, :await, [task, 5000]}} end test "await/1 exits on task throw" do Process.flag(:trap_exit, true) task = Task.async(fn -> throw :unknown end) assert {{{:nocatch, :unknown}, _}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task error" do Process.flag(:trap_exit, true) task = Task.async(fn -> raise "oops" end) assert {{%RuntimeError{}, _}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task undef module error" do Process.flag(:trap_exit, true) task = Task.async(&:module_does_not_exist.undef/0) assert {{:undef, [{:module_does_not_exist, :undef, _, _} | _]}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task undef function error" do Process.flag(:trap_exit, true) task = Task.async(&TaskTest.undef/0) assert {{:undef, [{TaskTest, :undef, _, _} | _]}, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on task exit" do Process.flag(:trap_exit, true) task = Task.async(fn -> exit :unknown end) assert {:unknown, {Task, :await, [^task, 5000]}} = catch_exit(Task.await(task)) end test "await/1 exits on :noconnection" do ref = make_ref() task = %Task{ref: ref, pid: self()} send self(), {:DOWN, ref, self(), self(), :noconnection} assert catch_exit(Task.await(task)) |> elem(0) == {:nodedown, :nonode@nohost} end test "find/2" do task = %Task{ref: make_ref} assert Task.find([task], {make_ref, :ok}) == nil assert Task.find([task], {task.ref, :ok}) == {:ok, task} assert Task.find([task], {:DOWN, make_ref, :process, self, :kill}) == nil msg = {:DOWN, task.ref, :process, self, :kill} assert catch_exit(Task.find([task], msg)) == {:kill, {Task, :find, [[task], msg]}} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/test_helper.exs000066400000000000000000000047031254730255300244750ustar00rootroot00000000000000ExUnit.start [trace: "--trace" in System.argv] # Beam files compiled on demand path = Path.expand("../../tmp/beams", __DIR__) File.rm_rf!(path) File.mkdir_p!(path) Code.prepend_path(path) Code.compiler_options debug_info: true defmodule PathHelpers do def fixture_path() do Path.expand("fixtures", __DIR__) end def tmp_path() do Path.expand("../../tmp", __DIR__) end def fixture_path(extra) do Path.join(fixture_path, extra) end def tmp_path(extra) do Path.join(tmp_path, extra) end def elixir(args) do runcmd(elixir_executable, args) end def elixir_executable do executable_path("elixir") end def elixirc(args) do runcmd(elixirc_executable, args) end def elixirc_executable do executable_path("elixirc") end def write_beam({:module, name, bin, _} = res) do File.mkdir_p!(unquote(path)) beam_path = Path.join(unquote(path), Atom.to_string(name) <> ".beam") File.write!(beam_path, bin) res end defp runcmd(executable, args) do :os.cmd :binary.bin_to_list("#{executable} #{IO.chardata_to_string(args)}#{redirect_std_err_on_win}") end defp executable_path(name) do Path.expand("../../../../bin/#{name}#{executable_extension}", __DIR__) end if match? {:win32, _}, :os.type do def windows?, do: true def executable_extension, do: ".bat" def redirect_std_err_on_win, do: " 2>&1" else def windows?, do: false def executable_extension, do: "" def redirect_std_err_on_win, do: "" end end defmodule CompileAssertion do import ExUnit.Assertions def assert_compile_fail(exception, string) do case format_rescue(string) do {^exception, _} -> :ok error -> raise ExUnit.AssertionError, left: inspect(elem(error, 0)), right: inspect(exception), message: "Expected match" end end def assert_compile_fail(exception, message, string) do case format_rescue(string) do {^exception, ^message} -> :ok error -> raise ExUnit.AssertionError, left: "#{inspect elem(error, 0)}[message: #{inspect elem(error, 1)}]", right: "#{inspect exception}[message: #{inspect message}]", message: "Expected match" end end defp format_rescue(expr) do result = try do :elixir.eval(to_char_list(expr), []) nil rescue error -> {error.__struct__, Exception.message(error)} end result || flunk("Expected expression to fail") end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/tuple_test.exs000066400000000000000000000026101254730255300243420ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule TupleTest do use ExUnit.Case, async: true test :elem do assert elem({:a, :b, :c}, 1) == :b end test :put_elem do assert put_elem({:a, :b, :c}, 1, :d) == {:a, :d, :c} end test :keywords do assert {1, 2, three: :four} == {1, 2, [three: :four]} end test :optional_comma do assert {1} == {1,} assert {1, 2, 3} == {1, 2, 3,} end test :partial_application do assert (&{&1, 2}).(1) == {1, 2} assert (&{&1, &2}).(1, 2) == {1, 2} assert (&{&2, &1}).(2, 1) == {1, 2} end # Tuple module # We check two variants due to inlining. test :duplicate do assert Tuple.duplicate(:foo, 0) == {} assert Tuple.duplicate(:foo, 3) == {:foo, :foo, :foo} mod = Tuple assert mod.duplicate(:foo, 0) == {} assert mod.duplicate(:foo, 3) == {:foo, :foo, :foo} end test :insert_at do assert Tuple.insert_at({:bar, :baz}, 0, :foo) == {:foo, :bar, :baz} mod = Tuple assert mod.insert_at({:bar, :baz}, 0, :foo) == {:foo, :bar, :baz} end test :append do assert Tuple.append({:foo, :bar}, :baz) == {:foo, :bar, :baz} mod = Tuple assert mod.append({:foo, :bar}, :baz) == {:foo, :bar, :baz} end test :delete_at do assert Tuple.delete_at({:foo, :bar, :baz}, 0) == {:bar, :baz} mod = Tuple assert mod.delete_at({:foo, :bar, :baz}, 0) == {:bar, :baz} end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/uri_test.exs000066400000000000000000000205751254730255300240220ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule URITest do use ExUnit.Case, async: true test :encode do assert URI.encode("4_test.is-s~") == "4_test.is-s~" assert URI.encode("\r\n&<%>\" ゆ", &URI.char_unreserved?/1) == "%0D%0A%26%3C%25%3E%22%20%E3%82%86" end test :encode_www_form do assert URI.encode_www_form("4test ~1.x") == "4test+~1.x" assert URI.encode_www_form("poll:146%") == "poll%3A146%25" assert URI.encode_www_form("/\n+/ゆ") == "%2F%0A%2B%2F%E3%82%86" end test :encode_query do assert URI.encode_query([{:foo, :bar}, {:baz, :quux}]) == "foo=bar&baz=quux" assert URI.encode_query([{"foo", "bar"}, {"baz", "quux"}]) == "foo=bar&baz=quux" assert URI.encode_query([{"foo z", :bar}]) == "foo+z=bar" assert_raise ArgumentError, fn -> URI.encode_query([{"foo", 'bar'}]) end end test :decode_query do assert URI.decode_query("", []) == [] assert URI.decode_query("", %{}) == %{} assert URI.decode_query("q=search%20query&cookie=ab%26cd&block+buster=") == %{"block buster" => "", "cookie" => "ab&cd", "q" => "search query"} assert URI.decode_query("something=weird%3Dhappening") == %{"something" => "weird=happening"} assert URI.decode_query("garbage") == %{"garbage" => nil} assert URI.decode_query("=value") == %{"" => "value"} assert URI.decode_query("something=weird=happening") == %{"something" => "weird=happening"} end test :decoder do decoder = URI.query_decoder("q=search%20query&cookie=ab%26cd&block%20buster=") expected = [{"q", "search query"}, {"cookie", "ab&cd"}, {"block buster", ""}] assert Enum.map(decoder, &(&1)) == expected end test :decode do assert URI.decode("%0D%0A%26%3C%25%3E%22%20%E3%82%86") == "\r\n&<%>\" ゆ" assert URI.decode("%2f%41%4a%55") == "/AJU" assert URI.decode("4_t+st.is-s~") == "4_t+st.is-s~" assert_raise ArgumentError, ~R/malformed URI/, fn -> URI.decode("% invalid") end assert_raise ArgumentError, ~R/malformed URI/, fn -> URI.decode("invalid%") end end test :decode_www_form do assert URI.decode_www_form("%3Eval+ue%2B") == ">val ue+" assert URI.decode_www_form("%E3%82%86+") == "ゆ " end test :parse_uri do assert URI.parse(uri = %URI{scheme: "http", host: "foo.com"}) == uri end test :parse_http do assert %URI{scheme: "http", host: "foo.com", path: "/path/to/something", query: "foo=bar&bar=foo", fragment: "fragment", port: 80, authority: "foo.com", userinfo: nil} == URI.parse("http://foo.com/path/to/something?foo=bar&bar=foo#fragment") end test :parse_https do assert %URI{scheme: "https", host: "foo.com", authority: "foo.com", query: nil, fragment: nil, port: 443, path: nil, userinfo: nil} == URI.parse("https://foo.com") end test :parse_file do assert %URI{scheme: "file", host: nil, path: "/foo/bar/baz", userinfo: nil, query: nil, fragment: nil, port: nil, authority: nil} == URI.parse("file:///foo/bar/baz") end test :parse_ftp do assert %URI{scheme: "ftp", host: "private.ftp-servers.example.com", userinfo: "user001:secretpassword", authority: "user001:secretpassword@private.ftp-servers.example.com", path: "/mydirectory/myfile.txt", query: nil, fragment: nil, port: 21} == URI.parse("ftp://user001:secretpassword@private.ftp-servers.example.com/mydirectory/myfile.txt") end test :parse_sftp do assert %URI{scheme: "sftp", host: "private.ftp-servers.example.com", userinfo: "user001:secretpassword", authority: "user001:secretpassword@private.ftp-servers.example.com", path: "/mydirectory/myfile.txt", query: nil, fragment: nil, port: 22} == URI.parse("sftp://user001:secretpassword@private.ftp-servers.example.com/mydirectory/myfile.txt") end test :parse_tftp do assert %URI{scheme: "tftp", host: "private.ftp-servers.example.com", userinfo: "user001:secretpassword", authority: "user001:secretpassword@private.ftp-servers.example.com", path: "/mydirectory/myfile.txt", query: nil, fragment: nil, port: 69} == URI.parse("tftp://user001:secretpassword@private.ftp-servers.example.com/mydirectory/myfile.txt") end test :parse_ldap do assert %URI{scheme: "ldap", host: nil, authority: nil, userinfo: nil, path: "/dc=example,dc=com", query: "?sub?(givenName=John)", fragment: nil, port: 389} == URI.parse("ldap:///dc=example,dc=com??sub?(givenName=John)") assert %URI{scheme: "ldap", host: "ldap.example.com", authority: "ldap.example.com", userinfo: nil, path: "/cn=John%20Doe,dc=example,dc=com", fragment: nil, port: 389, query: nil} == URI.parse("ldap://ldap.example.com/cn=John%20Doe,dc=example,dc=com") end test :parse_splits_authority do assert %URI{scheme: "http", host: "foo.com", path: nil, query: nil, fragment: nil, port: 4444, authority: "foo:bar@foo.com:4444", userinfo: "foo:bar"} == URI.parse("http://foo:bar@foo.com:4444") assert %URI{scheme: "https", host: "foo.com", path: nil, query: nil, fragment: nil, port: 443, authority: "foo:bar@foo.com", userinfo: "foo:bar"} == URI.parse("https://foo:bar@foo.com") assert %URI{scheme: "http", host: "foo.com", path: nil, query: nil, fragment: nil, port: 4444, authority: "foo.com:4444", userinfo: nil} == URI.parse("http://foo.com:4444") end test :default_port do assert URI.default_port("http") == 80 try do URI.default_port("http", 8000) assert URI.default_port("http") == 8000 after URI.default_port("http", 80) end assert URI.default_port("unknown") == nil URI.default_port("unknown", 13) assert URI.default_port("unknown") == 13 end test :parse_bad_uris do assert URI.parse("") assert URI.parse("https:??@?F?@#>F//23/") assert URI.parse(":https").path == ":https" assert URI.parse("https").path == "https" assert URI.parse("ht\0tps://foo.com").path == "ht\0tps://foo.com" end test :ipv6_addresses do addrs = [ "::", # undefined "::1", # loopback "1080::8:800:200C:417A", # unicast "FF01::101", # multicast "2607:f3f0:2:0:216:3cff:fef0:174a", # abbreviated "2607:f3F0:2:0:216:3cFf:Fef0:174A", # mixed hex case "2051:0db8:2d5a:3521:8313:ffad:1242:8e2e", # complete "::00:192.168.10.184" # embedded IPv4 ] Enum.each addrs, fn(addr) -> simple_uri = URI.parse("http://[#{addr}]/") assert simple_uri.host == addr userinfo_uri = URI.parse("http://user:pass@[#{addr}]/") assert userinfo_uri.host == addr assert userinfo_uri.userinfo == "user:pass" port_uri = URI.parse("http://[#{addr}]:2222/") assert port_uri.host == addr assert port_uri.port == 2222 userinfo_port_uri = URI.parse("http://user:pass@[#{addr}]:2222/") assert userinfo_port_uri.host == addr assert userinfo_port_uri.userinfo == "user:pass" assert userinfo_port_uri.port == 2222 end end test :downcase_scheme do assert URI.parse("hTtP://google.com").scheme == "http" end test :to_string do assert to_string(URI.parse("http://google.com")) == "http://google.com" assert to_string(URI.parse("http://google.com:443")) == "http://google.com:443" assert to_string(URI.parse("https://google.com:443")) == "https://google.com" assert to_string(URI.parse("http://lol:wut@google.com")) == "http://lol:wut@google.com" assert to_string(URI.parse("http://google.com/elixir")) == "http://google.com/elixir" assert to_string(URI.parse("http://google.com?q=lol")) == "http://google.com?q=lol" assert to_string(URI.parse("http://google.com?q=lol#omg")) == "http://google.com?q=lol#omg" assert to_string(URI.parse("//google.com/elixir")) == "//google.com/elixir" assert to_string(URI.parse("//google.com:8080/elixir")) == "//google.com:8080/elixir" assert to_string(URI.parse("//user:password@google.com/")) == "//user:password@google.com/" end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/elixir/version_test.exs000066400000000000000000000143611254730255300247040ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule VersionTest do use ExUnit.Case, async: true alias Version.Parser, as: P alias Version, as: V test "compare" do assert :gt == V.compare("1.0.1", "1.0.0") assert :gt == V.compare("1.1.0", "1.0.1") assert :gt == V.compare("2.1.1", "1.2.2") assert :gt == V.compare("1.0.0", "1.0.0-dev") assert :gt == V.compare("1.2.3-dev", "0.1.2") assert :gt == V.compare("1.0.0-a.b", "1.0.0-a") assert :gt == V.compare("1.0.0-b", "1.0.0-a.b") assert :gt == V.compare("1.0.0-a", "1.0.0-0") assert :gt == V.compare("1.0.0-a.b", "1.0.0-a.a") assert :lt == V.compare("1.0.0", "1.0.1") assert :lt == V.compare("1.0.1", "1.1.0") assert :lt == V.compare("1.2.2", "2.1.1") assert :lt == V.compare("1.0.0-dev", "1.0.0") assert :lt == V.compare("0.1.2", "1.2.3-dev") assert :lt == V.compare("1.0.0-a", "1.0.0-a.b") assert :lt == V.compare("1.0.0-a.b", "1.0.0-b") assert :lt == V.compare("1.0.0-0", "1.0.0-a") assert :lt == V.compare("1.0.0-a.a", "1.0.0-a.b") assert :eq == V.compare("1.0.0", "1.0.0") assert :eq == V.compare("1.0.0-dev", "1.0.0-dev") assert :eq == V.compare("1.0.0-a", "1.0.0-a") end test "invalid compare" do assert_raise V.InvalidVersionError, fn -> V.compare("1.0", "1.0.0") end assert_raise V.InvalidVersionError, fn -> V.compare("1.0.0-dev", "1.0") end assert_raise V.InvalidVersionError, fn -> V.compare("foo", "1.0.0-a") end end test "lexes specifications properly" do assert P.lexer("== != > >= < <= ~>", []) == [:'==', :'!=', :'>', :'>=', :'<', :'<=', :'~>'] assert P.lexer("2.3.0", []) == [:'==', "2.3.0"] assert P.lexer("!2.3.0", []) == [:'!=', "2.3.0"] assert P.lexer(">>=", []) == [:'>', :'>='] assert P.lexer(">2.4.0", []) == [:'>', "2.4.0"] assert P.lexer(" > 2.4.0", []) == [:'>', "2.4.0"] end test "parse" do assert {:ok, %V{major: 1, minor: 2, patch: 3}} = V.parse("1.2.3") assert {:ok, %V{major: 1, minor: 4, patch: 5}} = V.parse("1.4.5+ignore") assert {:ok, %V{major: 1, minor: 4, patch: 5, pre: ["6-g3318bd5"]}} = V.parse("1.4.5-6-g3318bd5") assert {:ok, %V{major: 1, minor: 4, patch: 5, pre: [6, 7, "eight"]}} = V.parse("1.4.5-6.7.eight") assert {:ok, %V{major: 1, minor: 4, patch: 5, pre: ["6-g3318bd5"]}} = V.parse("1.4.5-6-g3318bd5+ignore") assert :error = V.parse("foobar") assert :error = V.parse("2.3") assert :error = V.parse("2") assert :error = V.parse("2.3.0-01") end test "to_string" do assert V.parse("1.0.0") |> elem(1) |> to_string == "1.0.0" assert V.parse("1.0.0-dev") |> elem(1) |> to_string == "1.0.0-dev" assert V.parse("1.0.0+lol") |> elem(1) |> to_string == "1.0.0+lol" assert V.parse("1.0.0-dev+lol") |> elem(1) |> to_string == "1.0.0-dev+lol" assert V.parse("1.0.0-0") |> elem(1) |> to_string == "1.0.0-0" assert V.parse("1.0.0-rc.0") |> elem(1) |> to_string == "1.0.0-rc.0" end test "invalid match" do assert_raise V.InvalidVersionError, fn -> V.match?("foo", "2.3.0") end assert_raise V.InvalidVersionError, fn -> V.match?("2.3", "2.3.0") end assert_raise V.InvalidRequirementError, fn -> V.match?("2.3.0", "foo") end assert_raise V.InvalidRequirementError, fn -> V.match?("2.3.0", "2.3") end end test "==" do assert V.match?("2.3.0", "2.3.0") refute V.match?("2.4.0", "2.3.0") assert V.match?("2.3.0", "== 2.3.0") refute V.match?("2.4.0", "== 2.3.0") assert V.match?("1.0.0", "1.0.0") assert V.match?("1.0.0", "1.0.0") assert V.match?("1.2.3-alpha", "1.2.3-alpha") assert V.match?("0.9.3", "== 0.9.3+dev") end test "!=" do assert V.match?("2.4.0", "!2.3.0") refute V.match?("2.3.0", "!2.3.0") assert V.match?("2.4.0", "!= 2.3.0") refute V.match?("2.3.0", "!= 2.3.0") end test ">" do assert V.match?("2.4.0", "> 2.3.0") refute V.match?("2.2.0", "> 2.3.0") refute V.match?("2.3.0", "> 2.3.0") assert V.match?("1.2.3", "> 1.2.3-alpha") assert V.match?("1.2.3-alpha.1", "> 1.2.3-alpha") assert V.match?("1.2.3-alpha.beta.sigma", "> 1.2.3-alpha.beta") refute V.match?("1.2.3-alpha.10", "< 1.2.3-alpha.1") refute V.match?("0.10.2-dev", "> 0.10.2") end test ">=" do assert V.match?("2.4.0", ">= 2.3.0") refute V.match?("2.2.0", ">= 2.3.0") assert V.match?("2.3.0", ">= 2.3.0") assert V.match?("2.0.0", ">= 1.0.0") assert V.match?("1.0.0", ">= 1.0.0") end test "<" do assert V.match?("2.2.0", "< 2.3.0") refute V.match?("2.4.0", "< 2.3.0") refute V.match?("2.3.0", "< 2.3.0") assert V.match?("0.10.2-dev", "< 0.10.2") refute V.match?("1.0.0", "< 1.0.0-dev") refute V.match?("1.2.3-dev", "< 0.1.2") end test "<=" do assert V.match?("2.2.0", "<= 2.3.0") refute V.match?("2.4.0", "<= 2.3.0") assert V.match?("2.3.0", "<= 2.3.0") end test "~>" do assert V.match?("3.0.0", "~> 3.0") assert V.match?("3.2.0", "~> 3.0") refute V.match?("4.0.0", "~> 3.0") refute V.match?("4.4.0", "~> 3.0") assert V.match?("3.0.2", "~> 3.0.0") assert V.match?("3.0.0", "~> 3.0.0") refute V.match?("3.1.0", "~> 3.0.0") refute V.match?("3.4.0", "~> 3.0.0") assert V.match?("3.6.0", "~> 3.5") assert V.match?("3.5.0", "~> 3.5") refute V.match?("4.0.0", "~> 3.5") refute V.match?("5.0.0", "~> 3.5") assert V.match?("3.5.2", "~> 3.5.0") assert V.match?("3.5.4", "~> 3.5.0") refute V.match?("3.6.0", "~> 3.5.0") refute V.match?("3.6.3", "~> 3.5.0") assert V.match?("0.9.3", "~> 0.9.3-dev") refute V.match?("0.10.0", "~> 0.9.3-dev") refute V.match?("0.3.0-dev", "~> 0.2.0") assert_raise V.InvalidRequirementError, fn -> V.match?("3.0.0", "~> 3") end end test "and" do assert V.match?("0.9.3", "> 0.9.0 and < 0.10.0") refute V.match?("0.10.2", "> 0.9.0 and < 0.10.0") end test "or" do assert V.match?("0.9.1", "0.9.1 or 0.9.3 or 0.9.5") assert V.match?("0.9.3", "0.9.1 or 0.9.3 or 0.9.5") assert V.match?("0.9.5", "0.9.1 or 0.9.3 or 0.9.5") refute V.match?("0.9.6", "0.9.1 or 0.9.3 or 0.9.5") end end elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/000077500000000000000000000000001254730255300214065ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/atom_test.erl000066400000000000000000000022731254730255300241150ustar00rootroot00000000000000-module(atom_test). -export([kv/1]). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. kv([{Key, nil}]) -> Key. atom_with_punctuation_test() -> {foo@bar, []} = eval(":foo@bar"), {'a?', []} = eval(":a?"), {'a!', []} = eval(":a!"), {'||', []} = eval(":||"), {'...', []} = eval(":..."). atom_quoted_call_test() -> {3, []} = eval("Kernel.'+'(1, 2)"). kv_with_quotes_test() -> {'foo bar', []} = eval(":atom_test.kv(\"foo bar\": nil)"). kv_with_interpolation_test() -> {'foo', []} = eval(":atom_test.kv(\"#{\"foo\"}\": nil)"), {'foo', []} = eval(":atom_test.kv(\"#{\"fo\"}o\": nil)"), {'foo', _} = eval("a = \"f\"; :atom_test.kv(\"#{a}#{\"o\"}o\": nil)"). quoted_atom_test() -> {foo, []} = eval(":\"foo\""), {foo, []} = eval(":'foo'"), {'foo.Bar', []} = eval(":\"foo.Bar\""). atom_with_interpolation_test() -> {foo, []} = eval(":\"f#{\"o\"}o\""), {foo, _} = eval("a=\"foo\"; :\"#{a}\""), {foo, _} = eval("a=\"oo\"; :\"f#{a}\""), {foo, _} = eval("a=\"fo\"; :\"#{a}o\""), {fof, _} = eval("a=\"f\"; :\"#{a}o#{a}\""). quoted_atom_chars_are_escaped_test() -> {'"', []} = eval(":\"\\\"\""). elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/control_test.erl000066400000000000000000000230661254730255300246400ustar00rootroot00000000000000-module(control_test). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. to_erl(String) -> Forms = elixir:'string_to_quoted!'(String, 1, <<"nofile">>, []), {Expr, _, _} = elixir:quoted_to_erl(Forms, elixir:env_for_eval([])), Expr. % Booleans booleans_test() -> {nil, _} = eval("nil"), {true, _} = eval("true"), {false, _} = eval("false"). % If if_else_kv_args_test() -> {1, _} = eval("if(true, do: 1)"), {nil, _} = eval("if(false, do: 1)"), {2, _} = eval("if(false, do: 1, else: 2)"). if_else_kv_blocks_test() -> {2, _} = eval("if(false) do\n1\nelse\n2\nend"), {2, _} = eval("if(false) do\n1\n3\nelse\n2\nend"), {2, _} = eval("if(false) do 1 else 2 end"), {2, _} = eval("if(false) do 1;else 2; end"), {3, _} = eval("if(false) do 1;else 2; 3; end"). vars_if_test() -> F = fun() -> {1, [{foo, 1}]} = eval("if foo = 1 do; true; else false; end; foo"), eval("defmodule Bar do\ndef foo, do: 1\ndef bar(x) do\nif x do; foo = 2; else foo = foo; end; foo; end\nend"), {1, _} = eval("Bar.bar(false)"), {2, _} = eval("Bar.bar(true)") end, test_helper:run_and_remove(F, ['Elixir.Bar']). multi_assigned_if_test() -> {3, _} = eval("x = 1\nif true do\nx = 2\nx = 3\nelse true\nend\nx"), {3, _} = eval("x = 1\nif true do\n^x = 1\nx = 2\nx = 3\nelse true\nend\nx"), {1, _} = eval("if true do\nx = 1\nelse true\nend\nx"), {nil, _} = eval("if false do\nx = 1\nelse true\nend\nx"). multi_line_if_test() -> {1, _} = eval("if true\ndo\n1\nelse\n2\nend"). % Try try_test() -> {2, _} = eval("try do\n:foo.bar\ncatch\n:error, :undef -> 2\nend"). try_else_test() -> {true, _} = eval("try do\n1\nelse 2 -> false\n1 -> true\nrescue\nErlangError -> nil\nend"), {true, _} = eval("try do\n1\nelse {x, y} -> false\nx -> true\nrescue\nErlangError -> nil\nend"), {true, _} = eval("try do\n{1, 2}\nelse {3, 4} -> false\n_ -> true\nrescue\nErlangError -> nil\nend"). % Receive receive_test() -> {10, _} = eval("send self(), :foo\nreceive do\n:foo -> 10\nend"), {20, _} = eval("send self(), :bar\nreceive do\n:foo -> 10\n_ -> 20\nend"), {30, _} = eval("receive do\nafter 1 -> 30\nend"). vars_receive_test() -> {10, _} = eval("send self(), :foo\nreceive do\n:foo ->\na = 10\n:bar -> nil\nend\na"), {nil, _} = eval("send self(), :bar\nreceive do\n:foo ->\nb = 10\n_ -> 20\nend\nb"), {30, _} = eval("receive do\n:foo -> nil\nafter\n1 -> c = 30\nend\nc"), {30, _} = eval("x = 1\nreceive do\n:foo -> nil\nafter\nx -> c = 30\nend\nc"). % Case case_test() -> {true, []} = eval("case 1 do\n2 -> false\n1 -> true\nend"), {true, []} = eval("case 1 do\n{x, y} -> false\nx -> true\nend"), {true, []} = eval("case {1, 2} do; {3, 4} -> false\n_ -> true\nend"). case_with_do_ambiguity_test() -> {true, _} = eval("case Atom.to_char_list(true) do\n_ -> true\nend"). case_with_match_do_ambiguity_test() -> {true, _} = eval("case x = Atom.to_char_list(true) do\n_ -> true\nend"). case_with_unary_do_ambiguity_test() -> {false, _} = eval("! case Atom.to_char_list(true) do\n_ -> true\nend"). multi_assigned_case_test() -> {3, _} = eval("x = 1\ncase true do\n true ->\nx = 2\nx = 3\n_ -> true\nend\nx"), {3, _} = eval("x = 1\ncase 1 do\n ^x -> x = 2\nx = 3\n_ -> true\nend\nx"), {1, _} = eval("case true do\ntrue -> x = 1\n_ -> true\nend\nx"), {nil, _} = eval("case true do\nfalse -> x = 1\n_ -> true\nend\nx"). vars_case_test() -> F = fun() -> eval("defmodule Bar do\ndef foo, do: 1\ndef bar(x) do\ncase x do\ntrue -> foo = 2\nfalse -> foo = foo\nend\nfoo\nend\nend"), {1, _} = eval("Bar.bar(false)"), {2, _} = eval("Bar.bar(true)") end, test_helper:run_and_remove(F, ['Elixir.Bar']). % Comparison equal_test() -> {true, _} = eval(":a == :a"), {true, _} = eval("1 == 1"), {true, _} = eval("{1, 2} == {1, 2}"), {false, _} = eval("1 == 2"), {false, _} = eval("{1, 2} == {1, 3}"). not_equal_test() -> {false, _} = eval(":a != :a"), {false, _} = eval("1 != 1"), {false, _} = eval("{1, 2} != {1, 2}"), {true, _} = eval("1 != 2"), {true, _} = eval("{1, 2} != {1, 3}"). not_exclamation_mark_test() -> {false, _} = eval("! :a"), {false, _} = eval("!true"), {false, _} = eval("!1"), {false, _} = eval("![]"), {true, _} = eval("!nil"), {true, _} = eval("!false"). notnot_exclamation_mark_test() -> {true, _} = eval("!! :a"), {true, _} = eval("!!true"), {true, _} = eval("!!1"), {true, _} = eval("!![]"), {false, _} = eval("!!nil"), {false, _} = eval("!!false"). less_greater_test() -> {true, _} = eval("1 < 2"), {true, _} = eval("1 < :a"), {false, _} = eval("1 < 1.0"), {false, _} = eval("1 < 1"), {true, _} = eval("1 <= 1.0"), {true, _} = eval("1 <= 1"), {true, _} = eval("1 <= :a"), {false, _} = eval("1 > 2"), {false, _} = eval("1 > :a"), {false, _} = eval("1 > 1.0"), {false, _} = eval("1 > 1"), {true, _} = eval("1 >= 1.0"), {true, _} = eval("1 >= 1"), {false, _} = eval("1 >= :a"). integer_and_float_test() -> {true, _} = eval("1 == 1"), {false, _} = eval("1 != 1"), {true, _} = eval("1 == 1.0"), {false, _} = eval("1 != 1.0"), {true, _} = eval("1 === 1"), {false, _} = eval("1 !== 1"), {false, _} = eval("1 === 1.0"), {true, _} = eval("1 !== 1.0"). and_test() -> F = fun() -> eval("defmodule Bar do\ndef foo, do: true\ndef bar, do: false\n def baz(x), do: x == 1\nend"), {true, _} = eval("true and true"), {false, _} = eval("true and false"), {false, _} = eval("false and true"), {false, _} = eval("false and false"), {true, _} = eval("Bar.foo and Bar.foo"), {false, _} = eval("Bar.foo and Bar.bar"), {true, _} = eval("Bar.foo and Bar.baz 1"), {false, _} = eval("Bar.foo and Bar.baz 2"), {true, _} = eval("false and false or true"), {3, _} = eval("Bar.foo and 1 + 2"), {false, _} = eval("Bar.bar and :erlang.error(:bad)"), ?assertError({badarg, 1}, eval("1 and 2")) end, test_helper:run_and_remove(F, ['Elixir.Bar']). or_test() -> F = fun() -> eval("defmodule Bar do\ndef foo, do: true\ndef bar, do: false\n def baz(x), do: x == 1\nend"), {true, _} = eval("true or true"), {true, _} = eval("true or false"), {true, _} = eval("false or true"), {false, _} = eval("false or false"), {true, _} = eval("Bar.foo or Bar.foo"), {true, _} = eval("Bar.foo or Bar.bar"), {false, _} = eval("Bar.bar or Bar.bar"), {true, _} = eval("Bar.bar or Bar.baz 1"), {false, _} = eval("Bar.bar or Bar.baz 2"), {3, _} = eval("Bar.bar or 1 + 2"), {true, _} = eval("Bar.foo or :erlang.error(:bad)"), ?assertError({badarg, 1}, eval("1 or 2")) end, test_helper:run_and_remove(F, ['Elixir.Bar']). not_test() -> {false, _} = eval("not true"), {true, _} = eval("not false"), ?assertError(badarg, eval("not 1")). andand_test() -> F = fun() -> eval("defmodule Bar do\ndef foo, do: true\ndef bar, do: false\n def baz(x), do: x == 1\nend"), {true, _} = eval("Kernel.&&(true, true)"), {true, _} = eval("true && true"), {false, _} = eval("true && false"), {false, _} = eval("false && true"), {false, _} = eval("false && false"), {nil, _} = eval("true && nil"), {nil, _} = eval("nil && true"), {false, _} = eval("false && nil"), {true, _} = eval("Bar.foo && Bar.foo"), {false, _} = eval("Bar.foo && Bar.bar"), {true, _} = eval("Bar.foo && Bar.baz 1"), {false, _} = eval("Bar.foo && Bar.baz 2"), {true, _} = eval("1 == 1 && 2 < 3"), {3, _} = eval("Bar.foo && 1 + 2"), {false, _} = eval("Bar.bar && :erlang.error(:bad)"), {2, _} = eval("1 && 2"), {nil, _} = eval("nil && 2") end, test_helper:run_and_remove(F, ['Elixir.Bar']). andand_with_literal_test() -> {[nil, nil, nil], _} = eval("[nil && 2, nil && 3, nil && 4]"). oror_test() -> F = fun() -> eval("defmodule Bar do\ndef foo, do: true\ndef bar, do: false\n def baz(x), do: x == 1\nend"), {true, _} = eval("Kernel.||(false, true)"), {true, _} = eval("true || true"), {true, _} = eval("true || false"), {true, _} = eval("false || true"), {false, _} = eval("false || false"), {false, _} = eval("nil || false"), {nil, _} = eval("false || nil"), {true, _} = eval("false || nil || true"), {true, _} = eval("Bar.foo || Bar.foo"), {true, _} = eval("Bar.foo || Bar.bar"), {false, _} = eval("Bar.bar || Bar.bar"), {true, _} = eval("Bar.bar || Bar.baz 1"), {false, _} = eval("Bar.bar || Bar.baz 2"), {false, _} = eval("1 == 2 || 2 > 3"), {3, _} = eval("Bar.bar || 1 + 2"), {true, _} = eval("Bar.foo || :erlang.error(:bad)"), {1, _} = eval("1 || 2"), {2, _} = eval("nil || 2"), {true, _} = eval("false && false || true") end, test_helper:run_and_remove(F, ['Elixir.Bar']). cond_line_test() -> {'case', 1, _, [{clause, 2, _, _, _}, {clause, 3, _, _, _}] } = to_erl("cond do\n 1 -> :ok\n 2 -> :ok\nend"). % Optimized optimized_if_test() -> {'case', _, _, [{clause, _, [{atom, _, false}], [], [{atom, _, else}]}, {clause, _, [{atom, _, true}], [], [{atom, _, do}]}] } = to_erl("if is_list([]), do: :do, else: :else"). optimized_andand_test() -> {'case', _, _, [{clause, _, [{var, _, Var}], [[{op, _, 'orelse', _, _}]], [{var, _, Var}]}, {clause, _, [{var, _, '_'}], [], [{atom, 0, done}]}] } = to_erl("is_list([]) && :done"). optimized_oror_test() -> {'case', _, _, [{clause, 1, [{var, 1, _}], [[{op, 1, 'orelse', _, _}]], [{atom, 0, done}]}, {clause, 1, [{var, 1, Var}], [], [{var, 1, Var}]}] } = to_erl("is_list([]) || :done"). no_after_in_try_test() -> {'try', _, [_], [_], _, []} = to_erl("try do :foo.bar() else _ -> :ok end"). elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/function_test.erl000066400000000000000000000075061254730255300250060ustar00rootroot00000000000000-module(function_test). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. function_arg_do_end_test() -> {3, _} = eval("if true do\n1 + 2\nend"), {nil, _} = eval("if true do end"). function_stab_end_test() -> {_, [{a, Fun1}]} = eval("a = fn -> end"), nil = Fun1(), {_, [{a, Fun2}]} = eval("a = fn() -> end"), nil = Fun2(), {_, [{a, Fun3}]} = eval("a = fn -> 1 + 2 end"), 3 = Fun3(). function_stab_many_test() -> {_, [{a, Fun}]} = eval("a = fn\n{:foo, x} -> x\n{:bar, x} -> x\nend"), 1 = Fun({foo, 1}), 2 = Fun({bar, 2}). function_stab_inline_test() -> {_, [{a, Fun}]} = eval("a = fn {:foo, x} -> x; {:bar, x} -> x end"), 1 = Fun({foo, 1}), 2 = Fun({bar, 2}). function_with_args_test() -> {Fun, _} = eval("fn(a, b) -> a + b end"), 3 = Fun(1, 2). function_with_kv_args_test() -> {Fun, _} = eval("fn(a, [other: b, another: c]) -> a + b + c end"), 6 = Fun(1, [{other, 2}, {another, 3}]). function_as_closure_test() -> {_, [{a, Res1}|_]} = eval("b = 1; a = fn -> b + 2 end"), 3 = Res1(). function_apply_test() -> {3, _} = eval("a = fn -> 3 end; apply a, []"). function_apply_with_args_test() -> {3, _} = eval("a = fn b -> b + 2 end; apply a, [1]"). function_apply_and_clojure_test() -> {3, _} = eval("b = 1; a = fn -> b + 2 end; apply a, []"). function_parens_test() -> {0, _} = eval("(fn() -> 0 end).()"), {1, _} = eval("(fn(1) -> 1 end).(1)"), {3, _} = eval("(fn(1, 2) -> 3 end).(1, 2)"), {0, _} = eval("(fn () -> 0 end).()"), {1, _} = eval("(fn (1) -> 1 end).(1)"), {3, _} = eval("(fn (1, 2) -> 3 end).(1, 2)"). %% Function calls function_call_test() -> {3, _} = eval("x = fn a, b -> a + b end\nx.(1, 2)"). function_call_without_arg_test() -> {3, _} = eval("x = fn -> 2 + 1 end\nx.()"). function_call_do_end_test() -> {[1, [{do, 2}, {else, 3}]], _} = eval("x = fn a, b -> [a, b] end\nx.(1) do\n2\nelse 3\nend"). function_call_with_assignment_test() -> {3, [{a, _}, {c, 3}]} = eval("a = fn x -> x + 2 end; c = a.(1)"). function_calls_with_multiple_expressions_test() -> {26, _} = eval("a = fn a, b -> a + b end; a.((3 + 4 - 1), (2 * 10))"). function_calls_with_multiple_args_with_line_breaks_test() -> {5, _} = eval("a = fn a, b -> a + b end; a.(\n3,\n2\n)"). function_calls_with_parenthesis_test() -> {3, [{a, _}, {b, 1}]} = eval("a = (fn x -> x + 2 end).(b = 1)"). function_call_with_a_single_space_test() -> {3, _} = eval("a = fn a, b -> a + b end; a. (1, 2)"), {3, _} = eval("a = fn a, b -> a + b end; a .(1, 2)"). function_call_with_spaces_test() -> {3, _} = eval("a = fn a, b -> a + b end; a . (1, 2)"). function_call_without_assigning_with_spaces_test() -> {3, _} = eval("(fn a, b -> a + b end) . (1, 2)"). function_call_with_assignment_and_spaces_test() -> {3, [{a, _}, {c, 3}]} = eval("a = fn x -> x + 2 end; c = a . (1)"). function_call_with_multiple_spaces_test() -> {3, _} = eval("a = fn a, b -> a + b end; a . (1, 2)"). function_call_with_multiline_test() -> {3, _} = eval("a = fn a, b -> a + b end; a . \n (1, 2)"). function_call_with_tabs_test() -> {3, _} = eval("a = fn a, b -> a + b end; a .\n\t(1, 2)"). function_call_with_args_and_nested_when_test() -> {Fun, _} = eval("fn a, b when a == 1 when b == 2 -> a + b end"), 3 = Fun(1, 2), 2 = Fun(0, 2), 1 = Fun(1, 0), ?assertError(function_clause, Fun(0, 0)). function_call_with_parens_args_and_nested_when_test() -> {Fun, _} = eval("fn\n(a, b) when a == 1 when b == 2 -> a + b\nend"), 3 = Fun(1, 2), 2 = Fun(0, 2), 1 = Fun(1, 0), ?assertError(function_clause, Fun(0, 0)). %% Partial application require_partial_application_test() -> {Fun, _} = eval("&List.flatten(&1)"), Fun = fun 'Elixir.List':flatten/1. import_partial_application_test() -> {Fun, _} = eval("&is_atom(&1)"), Fun = fun erlang:is_atom/1. elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/match_test.erl000066400000000000000000000073341254730255300242540ustar00rootroot00000000000000-module(match_test). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> eval(Content, []). eval(Content, Initial) -> {Value, Binding, _, _} = elixir:eval(Content, Initial), {Value, Binding}. no_assignment_test() -> {nil, []} = eval(""). % Var/assignment test arithmetic_test() -> ?assertError({badmatch, _}, eval("-1 = 1")). assignment_test() -> {1, [{a, 1}]} = eval("a = 1"). not_single_assignment_test() -> {2, [{a, 2}]} = eval("a = 1\na = 2\na"), {1, [{a, 1}]} = eval("{a, a} = {1, 1}\na"), {2, [{a, 2}]} = eval("a = 1\n{^a, a} = {1, 2}\na"), ?assertError({badmatch, _}, eval("{a, a} = {1, 2}")), ?assertError({badmatch, _}, eval("{1 = a, a} = {1, 2}")), ?assertError({badmatch, _}, eval("{a = 1, a} = {1, 2}")), ?assertError({badmatch, _}, eval("a = 0;{a, a} = {1, 2}")), ?assertError({badmatch, _}, eval("a = 0;{1 = a, a} = {1, 2}")), ?assertError({badmatch, _}, eval("a = 1\n^a = 2")). duplicated_assignment_on_module_with_tuple_test() -> F = fun() -> eval("defmodule Foo do\ndef v({a, _left}, {a, _right}), do: a\nend"), {1, _} = eval("Foo.v({1, :foo}, {1, :bar})"), ?assertError(function_clause, eval("Foo.v({1, :foo}, {2, :bar})")) end, test_helper:run_and_remove(F, ['Elixir.Foo']). duplicated_assignment_on_module_with_list_test() -> F = fun() -> eval("defmodule Foo do\ndef v([ a, _left ], [ a, _right ]), do: a\nend"), {1, _} = eval("Foo.v([ 1, :foo ], [ 1, :bar ])"), ?assertError(function_clause, eval("Foo.v([ 1, :foo ], [ 2, :bar ])")) end, test_helper:run_and_remove(F, ['Elixir.Foo']). multiline_assignment_test() -> {1, [{a, 1}]} = eval("a =\n1"), {1, [{a, 1}, {b, 1}]} = eval("a = 1\nb = 1"). multiple_assignment_test() -> {1, [{a, 1}, {b, 1}]} = eval("a = b = 1"). multiple_assignment_with_parens_test() -> {1, [{a, 1}, {b, 1}]} = eval("a = (b = 1)"). multiple_assignment_with_left_parens_test() -> {1, [{a, 1}, {b, 1}]} = eval("(a) = (b = 1)"). multiple_assignment_with_expression_test() -> {-4, [{a, -4}, {b, -4}]} = eval("a = (b = -(2 * 2))"). multiple_assignment_with_binding_expression_test() -> {3, [{a, 3}, {b, 1}]} = eval("a = (2 + b)", [{b, 1}]). underscore_assignment_test() -> {1, []} = eval("_ = 1"). assignment_precedence_test() -> {_, [{x, {'__block__', _, [1, 2, 3]}}]} = eval("x = quote do\n1\n2\n3\nend"). % Tuples match simple_tuple_test() -> {{}, _} = eval("a = {}"), {{1, 2, 3}, _} = eval("a = {1, 2, 3}"), {{1, 2, 3}, _} = eval("a = {1, 1 + 1, 3}"), {{1, {2}, 3}, _} = eval("a = {1, {2}, 3}"). tuple_match_test() -> {_, _} = eval("{1, 2, 3} = {1, 2, 3}"), ?assertError({badmatch, _}, eval("{1, 3, 2} = {1, 2, 3}")). % Lists match simple_list_test() -> {[], _} = eval("a = []"), {[1, 2, 3], _} = eval("a = [1, 2, 3]"), {[1, 2, 3], _} = eval("a = [1, 1 + 1, 3]"), {[1, [2], 3], _} = eval("a = [1, [2], 3]"), {[1, {2}, 3], _} = eval("a = [1, {2}, 3]"). list_match_test() -> {_, _} = eval("[1, 2, 3] = [1, 2, 3]"), ?assertError({badmatch, _}, eval("[1, 3, 2] = [1, 2, 3]")). list_vars_test() -> {[3, 1], [{x, 3}]} = eval("x = 1\n[x = x + 2, x]"). head_and_tail_test() -> {_, [{h, 1}, {t, [2, 3]}]} = eval("[h|t] = [1, 2, 3]"), {_, [{h, 2}, {t, [3]}]} = eval("[1, h|t] = [1, 2, 3]"), {_, [{t, [3]}]} = eval("[1, 2|t] = [1, 2, 3]"), {_, [{h, 1}]} = eval("[h|[2, 3]] = [1, 2, 3]"), {_, [{t, [2, 3]}]} = eval("[+1|t] = [1, 2, 3]"), ?assertError({badmatch, _}, eval("[2, h|t] = [1, 2, 3]")). % Keyword match orrdict_match_test() -> {[{a, 1}, {b, 2}], _} = eval("a = [a: 1, b: 2]"). % Function match function_clause_test() -> F = fun() -> eval("defmodule Foo do\ndef a([{_k, _}=e|_]), do: e\nend"), {{foo, bar}, _} = eval("Foo.a([{:foo, :bar}])") end, test_helper:run_and_remove(F, ['Elixir.Foo']).elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/module_test.erl000066400000000000000000000064721254730255300244470ustar00rootroot00000000000000-module(module_test). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. definition_test() -> F = fun() -> eval("defmodule Foo.Bar.Baz, do: nil") end, test_helper:run_and_remove(F, ['Elixir.Foo.Bar.Baz']). module_vars_test() -> F = fun() -> eval("a = 1; b = 2; c = 3; defmodule Foo do\n1 = a; 2 = b; 3 = c\nend") end, test_helper:run_and_remove(F, ['Elixir.Foo']). function_test() -> F = fun() -> eval("defmodule Foo.Bar.Baz do\ndef sum(a, b) do\na + b\nend\nend"), 3 = 'Elixir.Foo.Bar.Baz':sum(1, 2) end, test_helper:run_and_remove(F, ['Elixir.Foo.Bar.Baz']). quote_unquote_splicing_test() -> {{'{}', [], [1, 2, 3, 4, 5]}, _} = eval("x = [2, 3, 4]\nquote do: {1, unquote_splicing(x), 5}"). def_shortcut_test() -> F = fun() -> {1, []} = eval("defmodule Foo do\ndef version, do: 1\nend\nFoo.version") end, test_helper:run_and_remove(F, ['Elixir.Foo']). macro_test() -> F = fun() -> {'Elixir.Foo', []} = eval("defmodule Foo do\ndef version, do: __MODULE__\nend\nFoo.version"), {nil, []} = eval("__MODULE__") end, test_helper:run_and_remove(F, ['Elixir.Foo']). macro_line_test() -> F = fun() -> ?assertMatch({2, []}, eval("defmodule Foo do\ndef line, do: __ENV__.line\nend\nFoo.line")), ?assertMatch({1, []}, eval("__ENV__.line")) end, test_helper:run_and_remove(F, ['Elixir.Foo']). def_default_test() -> F = fun() -> eval("defmodule Foo do\ndef version(x \\\\ 1), do: x\nend"), ?assertEqual({1, []}, eval("Foo.version")), ?assertEqual({2, []}, eval("Foo.version(2)")) end, test_helper:run_and_remove(F, ['Elixir.Foo']). def_left_default_test() -> F = fun() -> eval("defmodule Foo do\ndef version(x \\\\ 1, y), do: x + y\nend"), ?assertEqual({4, []}, eval("Foo.version(3)")), ?assertEqual({5, []}, eval("Foo.version(2, 3)")) end, test_helper:run_and_remove(F, ['Elixir.Foo']). def_with_guard_test() -> F = fun() -> eval("defmodule Foo do\ndef v(x) when x < 10, do: true\ndef v(x) when x >= 10, do: false\nend"), {true, _} = eval("Foo.v(0)"), {false, _} = eval("Foo.v(20)") end, test_helper:run_and_remove(F, ['Elixir.Foo']). do_end_test() -> F = fun() -> eval("defmodule Foo do\ndef a, do: 1\ndefmodule Bar do\ndef b, do: 2\nend\ndef c, do: 3\nend"), {1, _} = eval("Foo.a"), {2, _} = eval("Foo.Bar.b"), {3, _} = eval("Foo.c") end, test_helper:run_and_remove(F, ['Elixir.Foo', 'Elixir.Foo.Bar']). nesting_test() -> F = fun() -> eval("defmodule Foo do\ndefmodule Elixir.Bar do\ndef b, do: 2\nend\nend"), {2, _} = eval("Bar.b") end, test_helper:run_and_remove(F, ['Elixir.Foo', 'Elixir.Bar']). dot_alias_test() -> {'Elixir.Foo.Bar.Baz', _} = eval("Foo.Bar.Baz"). single_ref_test() -> {'Elixir.Foo', _} = eval("Foo"), {'Elixir.Foo', _} = eval("Elixir.Foo"). nested_ref_test() -> {'Elixir.Foo.Bar.Baz', _} = eval("Foo.Bar.Baz"). module_with_elixir_as_a_name_test() -> ?assertError(#{'__struct__' := 'Elixir.CompileError'}, eval("defmodule Elixir do\nend")). dynamic_defmodule_test() -> F = fun() -> eval("defmodule Foo do\ndef a(name) do\ndefmodule name, do: (def x, do: 1)\nend\nend"), {_, _} = eval("Foo.a(Bar)"), {1, _} = eval("Bar.x") end, test_helper:run_and_remove(F, ['Elixir.Foo', 'Elixir.Bar']).elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/operators_test.erl000066400000000000000000000047611254730255300251770ustar00rootroot00000000000000-module(operators_test). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. separator_test() -> {334, []} = eval("3_34"), {600, []} = eval("2_00+45_5-5_5"). integer_sum_test() -> {3, []} = eval("1+2"), {6, []} = eval("1+2+3"), {6, []} = eval("1+2 +3"), {6, []} = eval("1 + 2 + 3"). integer_sum_minus_test() -> {-4, []} = eval("1-2-3"), {0, []} = eval("1+2-3"), {0, []} = eval("1 + 2 - 3"). integer_mult_test() -> {6, []} = eval("1*2*3"), {6, []} = eval("1 * 2 * 3"). integer_div_test() -> {0.5, []} = eval("1 / 2"), {2.0, []} = eval("4 / 2"). integer_div_rem_test() -> {2, []} = eval("div 5, 2"), {1, []} = eval("rem 5, 2"). integer_mult_div_test() -> {1.0, []} = eval("2*1/2"), {6.0, []} = eval("3 * 4 / 2"). integer_without_parens_test() -> {17, []} = eval("3 * 5 + 2"), {17, []} = eval("2 + 3 * 5"), {6.0, []} = eval("4 / 4 + 5"). integer_with_parens_test() -> {21, []} = eval("3 * (5 + 2)"), {21, []} = eval("3 * (((5 + (2))))"), {25, []} = eval("(2 + 3) * 5"), {0.25, []} = eval("4 / (11 + 5)"). integer_with_unary_test() -> {2, []} = eval("- 1 * - 2"). integer_eol_test() -> {3, []} = eval("1 +\n2"), {2, []} = eval("1 *\n2"), {8, []} = eval("1 + 2\n3 + 5"), {8, []} = eval("1 + 2\n\n\n3 + 5"), {8, []} = eval("1 + 2;\n\n3 + 5"), {8, []} = eval("1 + (\n2\n) + 3 + 2"), {8, []} = eval("1 + (\n\n 2\n\n) + 3 + 2"), {3, []} = eval(";1 + 2"), ?assertError(#{'__struct__' := 'Elixir.SyntaxError'}, eval("1 + 2;\n;\n3 + 5")). float_with_parens_and_unary_test() -> {-21.0, []} = eval("-3.0 * (5 + 2)"), {25.0, []} = eval("(2 + 3.0) * 5"), {0.25, []} = eval("4 / (11.0 + 5)"). operators_precedence_test() -> {2, _} = eval("max -1, 2"), {5, []} = eval("abs -10 + 5"), {15, []} = eval("abs(-10) + 5"). operators_variables_precedence_test() -> {30, _} = eval("a = 10\nb= 20\na+b"), {30, _} = eval("a = 10\nb= 20\na + b"). operators_variables_precedence_on_namespaces_test() -> F = fun() -> eval("defmodule Foo do; def l, do: 1; end; defmodule Bar do; def l(_x), do: 1; end"), {3, []} = eval("1 + Foo.l + 1"), {3, []} = eval("1 + Foo.l+1"), {2, []} = eval("1 + Bar.l +1") end, test_helper:run_and_remove(F, ['Elixir.Foo', 'Elixir.Bar']). add_add_op_test() -> {[1, 2, 3, 4], []} = eval("[1, 2] ++ [3, 4]"). minus_minus_op_test() -> {[1, 2], []} = eval("[1, 2, 3] -- [3]"), {[1, 2, 3], []} = eval("[1, 2, 3] -- [3] -- [3]").elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/string_test.erl000066400000000000000000000140311254730255300244560ustar00rootroot00000000000000-module(string_test). -include("../../src/elixir.hrl"). -include_lib("eunit/include/eunit.hrl"). eval(Content) -> {Value, Binding, _, _} = elixir:eval(Content, []), {Value, Binding}. extract_interpolations(String) -> case elixir_interpolation:extract(1, 1, #elixir_tokenizer{file = <<"nofile">>}, true, String ++ [$"], $") of {error, Error} -> Error; {_, _, Z, _} -> Z end. % Interpolations extract_interpolations_without_interpolation_test() -> [<<"foo">>] = extract_interpolations("foo"). extract_interpolations_with_escaped_interpolation_test() -> [<<"f#{o}o">>] = extract_interpolations("f\\#{o}o"), {1, 8, [<<"f#{o}o">>], []} = elixir_interpolation:extract(1, 2, #elixir_tokenizer{file = <<"nofile">>}, true, "f\\#{o}o\"", $"). extract_interpolations_with_interpolation_test() -> [<<"f">>, {{1,2,7}, [{atom, {1,4,6}, o}]}, <<"o">>] = extract_interpolations("f#{:o}o"). extract_interpolations_with_two_interpolations_test() -> [<<"f">>, {{1,2,7}, [{atom, {1,4,6}, o}]}, {{1,7,12}, [{atom, {1,9,11}, o}]}, <<"o">>] = extract_interpolations("f#{:o}#{:o}o"). extract_interpolations_with_only_two_interpolations_test() -> [{{1,1,6}, [{atom, {1,3,5}, o}]}, {{1,6,11}, [{atom, {1,8,10}, o}]}] = extract_interpolations("#{:o}#{:o}"). extract_interpolations_with_tuple_inside_interpolation_test() -> [<<"f">>, {{1,2,8}, [{'{', {1,4,5}}, {number, {1,5,6}, 1}, {'}', {1,6,7}}]}, <<"o">>] = extract_interpolations("f#{{1}}o"). extract_interpolations_with_many_expressions_inside_interpolation_test() -> [<<"f">>, {{1,2,3}, [{number, {1,4,5}, 1}, {eol, {1,5,6}}, {number, {2,1,2}, 2}]}, <<"o">>] = extract_interpolations("f#{1\n2}o"). extract_interpolations_with_right_curly_inside_string_inside_interpolation_test() -> [<<"f">>, {{1,2,10}, [{bin_string, {1,4,9}, [<<"f}o">>]}]}, <<"o">>] = extract_interpolations("f#{\"f}o\"}o"). extract_interpolations_with_left_curly_inside_string_inside_interpolation_test() -> [<<"f">>, {{1,2,10}, [{bin_string, {1,4,9}, [<<"f{o">>]}]}, <<"o">>] = extract_interpolations("f#{\"f{o\"}o"). extract_interpolations_with_escaped_quote_inside_string_inside_interpolation_test() -> [<<"f">>, {{1,2,11}, [{bin_string, {1,4,10}, [<<"f\"o">>]}]}, <<"o">>] = extract_interpolations("f#{\"f\\\"o\"}o"). extract_interpolations_with_less_than_operation_inside_interpolation_test() -> [<<"f">>, {{1,2,8}, [{number, {1,4,5}, 1}, {rel_op, {1,5,6}, '<'}, {number, {1,6,7}, 2}]}, <<"o">>] = extract_interpolations("f#{1<2}o"). extract_interpolations_with_an_escaped_character_test() -> [<<"f">>, {{1,2,17}, [{number, {1,4,7}, 7}, {rel_op, {1,8,9}, '>'}, {number, {1,10,13}, 7}]} ] = extract_interpolations("f#{?\\a > ?\\a }"). extract_interpolations_with_invalid_expression_inside_interpolation_test() -> {1, "invalid token: ", ":1}o\""} = extract_interpolations("f#{:1}o"). %% Bin strings empty_bin_string_test() -> {<<"">>, _} = eval("\"\""). simple_bin_string_test() -> {<<"foo">>, _} = eval("\"foo\""). bin_string_with_double_quotes_test() -> {<<"f\"o\"o">>, _} = eval("\"f\\\"o\\\"o\""). bin_string_with_newline_test() -> {<<"f\no">>, _} = eval("\"f\no\""). bin_string_with_slash_test() -> {<<"f\\o">>, _} = eval("\"f\\\\o\""). bin_string_with_bell_character_test() -> {<<"f\ao">>, _} = eval("\"f\ao\""). bin_string_with_interpolation_test() -> {<<"foo">>, _} = eval("\"f#{\"o\"}o\""). bin_string_with_another_string_inside_string_inside_interpolation_test() -> {<<"fbaro">>, _} = eval("\"f#{\"b#{\"a\"}r\"}o\""). bin_string_with_another_string_with_curly_inside_interpolation_test() -> {<<"fb}ro">>, _} = eval("\"f#{\"b}r\"}o\""). bin_string_with_atom_with_separator_inside_interpolation_test() -> {<<"f}o">>, _} = eval("\"f#{\"}\"}o\""). bin_string_with_lower_case_hex_interpolation_test() -> {<<"jklmno">>, _} = eval("\"\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\""). bin_string_with_upper_case_hex_interpolation_test() -> {<<"jklmno">>, _} = eval("\"\\x6A\\x6B\\x6C\\x6D\\x6E\\x6F\""). bin_string_without_interpolation_and_escaped_test() -> {<<"f#o">>, _} = eval("\"f\\#o\""). bin_string_with_escaped_interpolation_test() -> {<<"f#{'o}o">>, _} = eval("\"f\\#{'o}o\""). bin_string_with_the_end_of_line_slash_test() -> {<<"fo">>, _} = eval("\"f\\\no\""), {<<"fo">>, _} = eval("\"f\\\r\no\""). invalid_string_interpolation_test() -> ?assertError(#{'__struct__' := 'Elixir.TokenMissingError'}, eval("\"f#{some\"")), ?assertError(#{'__struct__' := 'Elixir.TokenMissingError'}, eval("\"f#{1+")). unterminated_string_interpolation_test() -> ?assertError(#{'__struct__' := 'Elixir.TokenMissingError'}, eval("\"foo")). %% List strings empty_list_string_test() -> {[], _} = eval("\'\'"). simple_list_string_test() -> {"foo", _} = eval("'foo'"). list_string_with_double_quotes_test() -> {"f'o'o", _} = eval("'f\\'o\\'o'"). list_string_with_newline_test() -> {"f\no", _} = eval("'f\no'"). list_string_with_slash_test() -> {"f\\o", _} = eval("'f\\\\o'"). list_string_with_bell_character_test() -> {"f\ao", _} = eval("'f\ao'"). list_string_with_interpolation_test() -> {"foo", _} = eval("'f#{\"o\"}o'"). list_string_with_another_string_with_curly_inside_interpolation_test() -> {"fb}ro", _} = eval("'f#{\"b}r\"}o'"). list_string_with_atom_with_separator_inside_interpolation_test() -> {"f}o", _} = eval("'f#{\"}\"}o'"). list_string_with_lower_case_hex_interpolation_test() -> {"JKLMNO", _} = eval("'\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f'"). list_string_with_upper_case_hex_interpolation_test() -> {"JKLMNO", _} = eval("'\\x4A\\x4B\\x4C\\x4D\\x4E\\x4F'"). list_string_without_interpolation_and_escaped_test() -> {"f#o", _} = eval("'f\\#o'"). list_string_with_escaped_interpolation_test() -> {"f#{\"o}o", _} = eval("'f\\#{\"o}o'"). list_string_with_the_end_of_line_slash_test() -> {"fo", _} = eval("'f\\\no'"), {"fo", _} = eval("'f\\\r\no'"). char_test() -> {99, []} = eval("?1 + ?2"), {10, []} = eval("?\\n"), {40, []} = eval("?\\("). %% Binaries bitstr_with_integer_test() -> {<<"fdo">>, _} = eval("<< \"f\", 50+50, \"o\" >>"). elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/test_helper.erl000066400000000000000000000021311254730255300244250ustar00rootroot00000000000000-module(test_helper). -export([test/0, run_and_remove/2, throw_elixir/1, throw_erlang/1]). -define(TESTS, [ atom_test, control_test, function_test, match_test, module_test, operators_test, string_test, tokenizer_test ]). test() -> application:ensure_all_started(elixir), case eunit:test(?TESTS) of error -> erlang:halt(1); _Res -> erlang:halt(0) end. % Execute a piece of code and purge given modules right after run_and_remove(Fun, Modules) -> try Fun() after [code:purge(Module) || Module <- Modules], [code:delete(Module) || Module <- Modules] end. % Throws an error with the Erlang Abstract Form from the Elixir string throw_elixir(String) -> Forms = elixir:'string_to_quoted!'(String, 1, <<"nofile">>, []), {Expr, _, _} = elixir:quoted_to_erl(Forms, elixir:env_for_eval([])), erlang:error(io:format("~p~n", [Expr])). % Throws an error with the Erlang Abstract Form from the Erlang string throw_erlang(String) -> {ok, Tokens, _} = erl_scan:string(String), {ok, [Form]} = erl_parse:parse_exprs(Tokens), erlang:error(io:format("~p~n", [Form])). elixir-lang-1.1.0~0.20150708/lib/elixir/test/erlang/tokenizer_test.erl000066400000000000000000000136331254730255300251710ustar00rootroot00000000000000-module(tokenizer_test). -include_lib("eunit/include/eunit.hrl"). tokenize(String) -> {ok, _Line, _Column, Result} = elixir_tokenizer:tokenize(String, 1, []), Result. tokenize_error(String) -> {error, Error, _, _} = elixir_tokenizer:tokenize(String, 1, []), Error. type_test() -> [{number, {1,1,2}, 1}, {type_op, {1,3,5}, '::'}, {number, {1,6,7}, 3}] = tokenize("1 :: 3"), [{identifier, {1,1,5}, name}, {'.', {1,5,6}}, {paren_identifier, {1,6,8}, '::'}, {'(', {1,8,9}}, {number, {1,9,10}, 3}, {')', {1,10,11}}] = tokenize("name.::(3)"). arithmetic_test() -> [{number, {1,1,2}, 1}, {dual_op, {1,3,4}, '+'}, {number, {1,5,6}, 2}, {dual_op, {1,7,8}, '+'}, {number, {1,9,10}, 3}] = tokenize("1 + 2 + 3"). op_kw_test() -> [{atom, {1,1,5}, foo}, {dual_op, {1,5,6}, '+'}, {atom, {1,6,10}, bar}] = tokenize(":foo+:bar"). scientific_test() -> [{number, {1,1,7}, 0.1}] = tokenize("1.0e-1"). hex_bin_octal_test() -> [{number, {1,1,5}, 255}] = tokenize("0xFF"), [{number, {1,1,5}, 255}] = tokenize("0xF_F"), [{number, {1,1,5}, 63}] = tokenize("0o77"), [{number, {1,1,5}, 63}] = tokenize("0o7_7"), [{number, {1,1,5}, 3}] = tokenize("0b11"), [{number, {1,1,5}, 3}] = tokenize("0b1_1"). unquoted_atom_test() -> [{atom, {1,1,3}, '+'}] = tokenize(":+"), [{atom, {1,1,3}, '-'}] = tokenize(":-"), [{atom, {1,1,3}, '*'}] = tokenize(":*"), [{atom, {1,1,3}, '/'}] = tokenize(":/"), [{atom, {1,1,3}, '='}] = tokenize(":="), [{atom, {1,1,4}, '&&'}] = tokenize(":&&"). quoted_atom_test() -> [{atom_unsafe, {1,1,11}, [<<"foo bar">>]}] = tokenize(":\"foo bar\""). oversized_atom_test() -> OversizedAtom = [$:|string:copies("a", 256)], {1, "atom length must be less than system limit", ":"} = tokenize_error(OversizedAtom). op_atom_test() -> [{atom, {1,1,6}, f0_1}] = tokenize(":f0_1"). kw_test() -> [{kw_identifier, {1,1,4}, do}] = tokenize("do: "), [{kw_identifier, {1,1,4}, a@}] = tokenize("a@: "), [{kw_identifier, {1,1,4}, 'A@'}] = tokenize("A@: "), [{kw_identifier, {1,1,5}, a@b}] = tokenize("a@b: "), [{kw_identifier, {1,1,5}, 'A@!'}] = tokenize("A@!: "), [{kw_identifier, {1,1,5}, 'a@!'}] = tokenize("a@!: "), [{kw_identifier_unsafe, {1,1,10}, [<<"foo bar">>]}] = tokenize("\"foo bar\": "). integer_test() -> [{number, {1,1,4}, 123}] = tokenize("123"), [{number, {1,1,4}, 123}, {';', {1,4,5}}] = tokenize("123;"), [{eol, {1,1,2}}, {number, {3,1,4}, 123}] = tokenize("\n\n123"), [{number, {1,3,6}, 123}, {number, {1,8,11}, 234}] = tokenize(" 123 234 "). float_test() -> [{number, {1,1,5}, 12.3}] = tokenize("12.3"), [{number, {1,1,5}, 12.3},{';', {1,5,6}}] = tokenize("12.3;"), [{eol, {1,1,2}}, {number, {3,1,5}, 12.3}] = tokenize("\n\n12.3"), [{number, {1,3,7}, 12.3}, {number, {1,9,13}, 23.4}] = tokenize(" 12.3 23.4 "). comments_test() -> [{number, {1,1,2}, 1},{eol, {1,3,4}},{number,{2,1,2},2}] = tokenize("1 # Comment\n2"). identifier_test() -> [{identifier,{1,1,4},abc}] = tokenize("abc "), [{identifier,{1,1,5},'abc?'}] = tokenize("abc?"), [{identifier,{1,1,5},'abc!'}] = tokenize("abc!"), [{identifier,{1,1,5},'a0c!'}] = tokenize("a0c!"), [{paren_identifier,{1,1,4},'a0c'},{'(',{1,4,5}},{')',{1,5,6}}] = tokenize("a0c()"), [{paren_identifier,{1,1,5},'a0c!'},{'(',{1,5,6}},{')',{1,6,7}}] = tokenize("a0c!()"). module_macro_test() -> [{identifier, {1,1,11}, '__MODULE__'}] = tokenize("__MODULE__"). triple_dot_test() -> [{identifier, {1,1,4}, '...'}] = tokenize("..."), [{'.', {1,1,2}}, {identifier, {1,3,5}, '..'}] = tokenize(". .."). dot_test() -> [{identifier, {1,1,4}, foo}, {'.', {1,4,5}}, {identifier, {1,5,8}, bar}, {'.', {1,8,9}}, {identifier, {1,9,12}, baz}] = tokenize("foo.bar.baz"). dot_keyword_test() -> [{identifier, {1,1,4}, foo}, {'.', {1,4,5}}, {identifier, {1,5,7}, do}] = tokenize("foo.do"). newline_test() -> [{identifier, {1,1,4}, foo}, {'.', {2,1,2}}, {identifier, {2,2,5}, bar}] = tokenize("foo\n.bar"), [{number, {1,1,2}, 1}, {two_op, {2,1,3}, '++'}, {number, {2,3,4}, 2}] = tokenize("1\n++2"). aliases_test() -> [{'aliases', {1,1,4}, ['Foo']}] = tokenize("Foo"), [{'aliases', {1,1,4}, ['Foo']}, {'.', {1,4,5}}, {'aliases', {1,5,8}, ['Bar']}, {'.', {1,8,9}}, {'aliases', {1,9,12}, ['Baz']}] = tokenize("Foo.Bar.Baz"). string_test() -> [{bin_string, {1,1,6}, [<<"foo">>]}] = tokenize("\"foo\""), [{bin_string, {1,1,6}, [<<"f\"">>]}] = tokenize("\"f\\\"\""), [{list_string, {1,1,6}, [<<"foo">>]}] = tokenize("'foo'"). empty_string_test() -> [{bin_string, {1,1,3}, [<<>>]}] = tokenize("\"\""), [{list_string, {1,1,3}, [<<>>]}] = tokenize("''"). addadd_test() -> [{identifier, {1,1,2}, x}, {two_op, {1,3,5}, '++'}, {identifier, {1,6,7}, y}] = tokenize("x ++ y"). space_test() -> [{op_identifier, {1,1,4}, foo}, {dual_op, {1,5,6}, '-'}, {number, {1,6,7}, 2}] = tokenize("foo -2"), [{op_identifier, {1,1,4}, foo}, {dual_op, {1,6,7}, '-'}, {number, {1,7,8}, 2}] = tokenize("foo -2"). invalid_space_test() -> {1, "invalid space character U+A0 before: ", "-2"} = tokenize_error("foo" ++ [16#A0] ++"-2"). chars_test() -> [{number, {1,1,3}, 97}] = tokenize("?a"), [{number, {1,1,3}, 99}] = tokenize("?c"), [{number, {1,1,4}, 0}] = tokenize("?\\0"), [{number, {1,1,4}, 7}] = tokenize("?\\a"), [{number, {1,1,4}, 10}] = tokenize("?\\n"), [{number, {1,1,4}, 92}] = tokenize("?\\\\"), [{number, {1,1,5}, 10}] = tokenize("?\\xa"), [{number, {1,1,7}, 10}] = tokenize("?\\x{a}"), [{number, {1,1,8}, 171}] = tokenize("?\\x{ab}"), [{number, {1,1,9}, 2748}] = tokenize("?\\x{abc}"), [{number, {1,1,10}, 43981}] = tokenize("?\\x{abcd}"), [{number, {1,1,11}, 703710}] = tokenize("?\\x{abcde}"), [{number, {1,1,12}, 1092557}] = tokenize("?\\x{10abcd}"). interpolation_test() -> [{bin_string, {1,1,9}, [<<"f">>, {{1,3,8}, [{identifier, {1,5,7}, oo}]}]}, {two_op, {1,10,12}, '<>'}, {bin_string, {1,13,15}, [<<>>]}] = tokenize("\"f#{oo}\" <> \"\""). elixir-lang-1.1.0~0.20150708/lib/elixir/unicode/000077500000000000000000000000001254730255300206055ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/elixir/unicode/GraphemeBreakProperty.txt000066400000000000000000002444571254730255300256300ustar00rootroot00000000000000000D ; CR # Cc 000A ; LF # Cc 0000..0009 ; Control # Cc [10] .. 000B..000C ; Control # Cc [2] .. 000E..001F ; Control # Cc [18] .. 007F..009F ; Control # Cc [33] .. 00AD ; Control # Cf SOFT HYPHEN 0600..0605 ; Control # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE 061C ; Control # Cf ARABIC LETTER MARK 06DD ; Control # Cf ARABIC END OF AYAH 070F ; Control # Cf SYRIAC ABBREVIATION MARK 180E ; Control # Cf MONGOLIAN VOWEL SEPARATOR 200B ; Control # Cf ZERO WIDTH SPACE 200E..200F ; Control # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK 2028 ; Control # Zl LINE SEPARATOR 2029 ; Control # Zp PARAGRAPH SEPARATOR 202A..202E ; Control # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE 2060..2064 ; Control # Cf [5] WORD JOINER..INVISIBLE PLUS 2065 ; Control # Cn 2066..206F ; Control # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES D800..DFFF ; Control # Cs [2048] .. FEFF ; Control # Cf ZERO WIDTH NO-BREAK SPACE FFF0..FFF8 ; Control # Cn [9] .. FFF9..FFFB ; Control # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR 110BD ; Control # Cf KAITHI NUMBER SIGN 1BCA0..1BCA3 ; Control # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP 1D173..1D17A ; Control # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE E0000 ; Control # Cn E0001 ; Control # Cf LANGUAGE TAG E0002..E001F ; Control # Cn [30] .. E0020..E007F ; Control # Cf [96] TAG SPACE..CANCEL TAG E0080..E00FF ; Control # Cn [128] .. E01F0..E0FFF ; Control # Cn [3600] .. 0300..036F ; Extend # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X 0483..0487 ; Extend # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE 0488..0489 ; Extend # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN 0591..05BD ; Extend # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG 05BF ; Extend # Mn HEBREW POINT RAFE 05C1..05C2 ; Extend # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT 05C4..05C5 ; Extend # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT 05C7 ; Extend # Mn HEBREW POINT QAMATS QATAN 0610..061A ; Extend # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA 064B..065F ; Extend # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW 0670 ; Extend # Mn ARABIC LETTER SUPERSCRIPT ALEF 06D6..06DC ; Extend # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN 06DF..06E4 ; Extend # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA 06E7..06E8 ; Extend # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON 06EA..06ED ; Extend # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM 0711 ; Extend # Mn SYRIAC LETTER SUPERSCRIPT ALAPH 0730..074A ; Extend # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH 07A6..07B0 ; Extend # Mn [11] THAANA ABAFILI..THAANA SUKUN 07EB..07F3 ; Extend # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE 0816..0819 ; Extend # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH 081B..0823 ; Extend # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A 0825..0827 ; Extend # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U 0829..082D ; Extend # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA 0859..085B ; Extend # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK 08E4..0902 ; Extend # Mn [31] ARABIC CURLY FATHA..DEVANAGARI SIGN ANUSVARA 093A ; Extend # Mn DEVANAGARI VOWEL SIGN OE 093C ; Extend # Mn DEVANAGARI SIGN NUKTA 0941..0948 ; Extend # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI 094D ; Extend # Mn DEVANAGARI SIGN VIRAMA 0951..0957 ; Extend # Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE 0962..0963 ; Extend # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL 0981 ; Extend # Mn BENGALI SIGN CANDRABINDU 09BC ; Extend # Mn BENGALI SIGN NUKTA 09BE ; Extend # Mc BENGALI VOWEL SIGN AA 09C1..09C4 ; Extend # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR 09CD ; Extend # Mn BENGALI SIGN VIRAMA 09D7 ; Extend # Mc BENGALI AU LENGTH MARK 09E2..09E3 ; Extend # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL 0A01..0A02 ; Extend # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI 0A3C ; Extend # Mn GURMUKHI SIGN NUKTA 0A41..0A42 ; Extend # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU 0A47..0A48 ; Extend # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI 0A4B..0A4D ; Extend # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA 0A51 ; Extend # Mn GURMUKHI SIGN UDAAT 0A70..0A71 ; Extend # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK 0A75 ; Extend # Mn GURMUKHI SIGN YAKASH 0A81..0A82 ; Extend # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA 0ABC ; Extend # Mn GUJARATI SIGN NUKTA 0AC1..0AC5 ; Extend # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E 0AC7..0AC8 ; Extend # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI 0ACD ; Extend # Mn GUJARATI SIGN VIRAMA 0AE2..0AE3 ; Extend # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL 0B01 ; Extend # Mn ORIYA SIGN CANDRABINDU 0B3C ; Extend # Mn ORIYA SIGN NUKTA 0B3E ; Extend # Mc ORIYA VOWEL SIGN AA 0B3F ; Extend # Mn ORIYA VOWEL SIGN I 0B41..0B44 ; Extend # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR 0B4D ; Extend # Mn ORIYA SIGN VIRAMA 0B56 ; Extend # Mn ORIYA AI LENGTH MARK 0B57 ; Extend # Mc ORIYA AU LENGTH MARK 0B62..0B63 ; Extend # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL 0B82 ; Extend # Mn TAMIL SIGN ANUSVARA 0BBE ; Extend # Mc TAMIL VOWEL SIGN AA 0BC0 ; Extend # Mn TAMIL VOWEL SIGN II 0BCD ; Extend # Mn TAMIL SIGN VIRAMA 0BD7 ; Extend # Mc TAMIL AU LENGTH MARK 0C00 ; Extend # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE 0C3E..0C40 ; Extend # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II 0C46..0C48 ; Extend # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI 0C4A..0C4D ; Extend # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA 0C55..0C56 ; Extend # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK 0C62..0C63 ; Extend # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL 0C81 ; Extend # Mn KANNADA SIGN CANDRABINDU 0CBC ; Extend # Mn KANNADA SIGN NUKTA 0CBF ; Extend # Mn KANNADA VOWEL SIGN I 0CC2 ; Extend # Mc KANNADA VOWEL SIGN UU 0CC6 ; Extend # Mn KANNADA VOWEL SIGN E 0CCC..0CCD ; Extend # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA 0CD5..0CD6 ; Extend # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK 0CE2..0CE3 ; Extend # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0D01 ; Extend # Mn MALAYALAM SIGN CANDRABINDU 0D3E ; Extend # Mc MALAYALAM VOWEL SIGN AA 0D41..0D44 ; Extend # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR 0D4D ; Extend # Mn MALAYALAM SIGN VIRAMA 0D57 ; Extend # Mc MALAYALAM AU LENGTH MARK 0D62..0D63 ; Extend # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL 0DCA ; Extend # Mn SINHALA SIGN AL-LAKUNA 0DCF ; Extend # Mc SINHALA VOWEL SIGN AELA-PILLA 0DD2..0DD4 ; Extend # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA 0DD6 ; Extend # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA 0DDF ; Extend # Mc SINHALA VOWEL SIGN GAYANUKITTA 0E31 ; Extend # Mn THAI CHARACTER MAI HAN-AKAT 0E34..0E3A ; Extend # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU 0E47..0E4E ; Extend # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN 0EB1 ; Extend # Mn LAO VOWEL SIGN MAI KAN 0EB4..0EB9 ; Extend # Mn [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU 0EBB..0EBC ; Extend # Mn [2] LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN LO 0EC8..0ECD ; Extend # Mn [6] LAO TONE MAI EK..LAO NIGGAHITA 0F18..0F19 ; Extend # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS 0F35 ; Extend # Mn TIBETAN MARK NGAS BZUNG NYI ZLA 0F37 ; Extend # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS 0F39 ; Extend # Mn TIBETAN MARK TSA -PHRU 0F71..0F7E ; Extend # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO 0F80..0F84 ; Extend # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA 0F86..0F87 ; Extend # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS 0F8D..0F97 ; Extend # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA 0F99..0FBC ; Extend # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA 0FC6 ; Extend # Mn TIBETAN SYMBOL PADMA GDAN 102D..1030 ; Extend # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU 1032..1037 ; Extend # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW 1039..103A ; Extend # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT 103D..103E ; Extend # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA 1058..1059 ; Extend # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL 105E..1060 ; Extend # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA 1071..1074 ; Extend # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE 1082 ; Extend # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA 1085..1086 ; Extend # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y 108D ; Extend # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE 109D ; Extend # Mn MYANMAR VOWEL SIGN AITON AI 135D..135F ; Extend # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK 1712..1714 ; Extend # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA 1732..1734 ; Extend # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD 1752..1753 ; Extend # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U 1772..1773 ; Extend # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U 17B4..17B5 ; Extend # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA 17B7..17BD ; Extend # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA 17C6 ; Extend # Mn KHMER SIGN NIKAHIT 17C9..17D3 ; Extend # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT 17DD ; Extend # Mn KHMER SIGN ATTHACAN 180B..180D ; Extend # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE 18A9 ; Extend # Mn MONGOLIAN LETTER ALI GALI DAGALGA 1920..1922 ; Extend # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U 1927..1928 ; Extend # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O 1932 ; Extend # Mn LIMBU SMALL LETTER ANUSVARA 1939..193B ; Extend # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I 1A17..1A18 ; Extend # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U 1A1B ; Extend # Mn BUGINESE VOWEL SIGN AE 1A56 ; Extend # Mn TAI THAM CONSONANT SIGN MEDIAL LA 1A58..1A5E ; Extend # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA 1A60 ; Extend # Mn TAI THAM SIGN SAKOT 1A62 ; Extend # Mn TAI THAM VOWEL SIGN MAI SAT 1A65..1A6C ; Extend # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW 1A73..1A7C ; Extend # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN 1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT 1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW 1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY 1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG 1B34 ; Extend # Mn BALINESE SIGN REREKAN 1B36..1B3A ; Extend # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA 1B3C ; Extend # Mn BALINESE VOWEL SIGN LA LENGA 1B42 ; Extend # Mn BALINESE VOWEL SIGN PEPET 1B6B..1B73 ; Extend # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG 1B80..1B81 ; Extend # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR 1BA2..1BA5 ; Extend # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU 1BA8..1BA9 ; Extend # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG 1BAB..1BAD ; Extend # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA 1BE6 ; Extend # Mn BATAK SIGN TOMPI 1BE8..1BE9 ; Extend # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE 1BED ; Extend # Mn BATAK VOWEL SIGN KARO O 1BEF..1BF1 ; Extend # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H 1C2C..1C33 ; Extend # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T 1C36..1C37 ; Extend # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA 1CD0..1CD2 ; Extend # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA 1CD4..1CE0 ; Extend # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA 1CE2..1CE8 ; Extend # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL 1CED ; Extend # Mn VEDIC SIGN TIRYAK 1CF4 ; Extend # Mn VEDIC TONE CANDRA ABOVE 1CF8..1CF9 ; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE 1DC0..1DF5 ; Extend # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE 1DFC..1DFF ; Extend # Mn [4] COMBINING DOUBLE INVERTED BREVE BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 200C..200D ; Extend # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER 20D0..20DC ; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0 ; Extend # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH 20E1 ; Extend # Mn COMBINING LEFT RIGHT ARROW ABOVE 20E2..20E4 ; Extend # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE 20E5..20F0 ; Extend # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE 2CEF..2CF1 ; Extend # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS 2D7F ; Extend # Mn TIFINAGH CONSONANT JOINER 2DE0..2DFF ; Extend # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS 302A..302D ; Extend # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK 302E..302F ; Extend # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK 3099..309A ; Extend # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK A66F ; Extend # Mn COMBINING CYRILLIC VZMET A670..A672 ; Extend # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN A674..A67D ; Extend # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK A69F ; Extend # Mn COMBINING CYRILLIC LETTER IOTIFIED E A6F0..A6F1 ; Extend # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS A802 ; Extend # Mn SYLOTI NAGRI SIGN DVISVARA A806 ; Extend # Mn SYLOTI NAGRI SIGN HASANTA A80B ; Extend # Mn SYLOTI NAGRI SIGN ANUSVARA A825..A826 ; Extend # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E A8C4 ; Extend # Mn SAURASHTRA SIGN VIRAMA A8E0..A8F1 ; Extend # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA A926..A92D ; Extend # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU A947..A951 ; Extend # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R A980..A982 ; Extend # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR A9B3 ; Extend # Mn JAVANESE SIGN CECAK TELU A9B6..A9B9 ; Extend # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT A9BC ; Extend # Mn JAVANESE VOWEL SIGN PEPET A9E5 ; Extend # Mn MYANMAR SIGN SHAN SAW AA29..AA2E ; Extend # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE AA31..AA32 ; Extend # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE AA35..AA36 ; Extend # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA AA43 ; Extend # Mn CHAM CONSONANT SIGN FINAL NG AA4C ; Extend # Mn CHAM CONSONANT SIGN FINAL M AA7C ; Extend # Mn MYANMAR SIGN TAI LAING TONE-2 AAB0 ; Extend # Mn TAI VIET MAI KANG AAB2..AAB4 ; Extend # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U AAB7..AAB8 ; Extend # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA AABE..AABF ; Extend # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK AAC1 ; Extend # Mn TAI VIET TONE MAI THO AAEC..AAED ; Extend # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI AAF6 ; Extend # Mn MEETEI MAYEK VIRAMA ABE5 ; Extend # Mn MEETEI MAYEK VOWEL SIGN ANAP ABE8 ; Extend # Mn MEETEI MAYEK VOWEL SIGN UNAP ABED ; Extend # Mn MEETEI MAYEK APUN IYEK FB1E ; Extend # Mn HEBREW POINT JUDEO-SPANISH VARIKA FE00..FE0F ; Extend # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 FE20..FE2D ; Extend # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON BELOW FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK 101FD ; Extend # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE 102E0 ; Extend # Mn COPTIC EPACT THOUSANDS MARK 10376..1037A ; Extend # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII 10A01..10A03 ; Extend # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R 10A05..10A06 ; Extend # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O 10A0C..10A0F ; Extend # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA 10A38..10A3A ; Extend # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW 10A3F ; Extend # Mn KHAROSHTHI VIRAMA 10AE5..10AE6 ; Extend # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW 11001 ; Extend # Mn BRAHMI SIGN ANUSVARA 11038..11046 ; Extend # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA 1107F..11081 ; Extend # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA 110B3..110B6 ; Extend # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI 110B9..110BA ; Extend # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA 11100..11102 ; Extend # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA 11127..1112B ; Extend # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU 1112D..11134 ; Extend # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA 11173 ; Extend # Mn MAHAJANI SIGN NUKTA 11180..11181 ; Extend # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA 111B6..111BE ; Extend # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O 1122F..11231 ; Extend # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI 11234 ; Extend # Mn KHOJKI SIGN ANUSVARA 11236..11237 ; Extend # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA 112DF ; Extend # Mn KHUDAWADI SIGN ANUSVARA 112E3..112EA ; Extend # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA 11301 ; Extend # Mn GRANTHA SIGN CANDRABINDU 1133C ; Extend # Mn GRANTHA SIGN NUKTA 1133E ; Extend # Mc GRANTHA VOWEL SIGN AA 11340 ; Extend # Mn GRANTHA VOWEL SIGN II 11357 ; Extend # Mc GRANTHA AU LENGTH MARK 11366..1136C ; Extend # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX 11370..11374 ; Extend # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA 114B0 ; Extend # Mc TIRHUTA VOWEL SIGN AA 114B3..114B8 ; Extend # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL 114BA ; Extend # Mn TIRHUTA VOWEL SIGN SHORT E 114BD ; Extend # Mc TIRHUTA VOWEL SIGN SHORT O 114BF..114C0 ; Extend # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA 114C2..114C3 ; Extend # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA 115AF ; Extend # Mc SIDDHAM VOWEL SIGN AA 115B2..115B5 ; Extend # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR 115BC..115BD ; Extend # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA 115BF..115C0 ; Extend # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA 11633..1163A ; Extend # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI 1163D ; Extend # Mn MODI SIGN ANUSVARA 1163F..11640 ; Extend # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA 116AB ; Extend # Mn TAKRI SIGN ANUSVARA 116AD ; Extend # Mn TAKRI VOWEL SIGN AA 116B0..116B5 ; Extend # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU 116B7 ; Extend # Mn TAKRI SIGN NUKTA 16AF0..16AF4 ; Extend # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE 16B30..16B36 ; Extend # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM 16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW 1BC9D..1BC9E ; Extend # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK 1D165 ; Extend # Mc MUSICAL SYMBOL COMBINING STEM 1D167..1D169 ; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 1D16E..1D172 ; Extend # Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5 1D17B..1D182 ; Extend # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE 1D185..1D18B ; Extend # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE 1D1AA..1D1AD ; Extend # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO 1D242..1D244 ; Extend # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME 1E8D0..1E8D6 ; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z 0903 ; SpacingMark # Mc DEVANAGARI SIGN VISARGA 093B ; SpacingMark # Mc DEVANAGARI VOWEL SIGN OOE 093E..0940 ; SpacingMark # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II 0949..094C ; SpacingMark # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU 094E..094F ; SpacingMark # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW 0982..0983 ; SpacingMark # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA 09BF..09C0 ; SpacingMark # Mc [2] BENGALI VOWEL SIGN I..BENGALI VOWEL SIGN II 09C7..09C8 ; SpacingMark # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI 09CB..09CC ; SpacingMark # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU 0A03 ; SpacingMark # Mc GURMUKHI SIGN VISARGA 0A3E..0A40 ; SpacingMark # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II 0A83 ; SpacingMark # Mc GUJARATI SIGN VISARGA 0ABE..0AC0 ; SpacingMark # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II 0AC9 ; SpacingMark # Mc GUJARATI VOWEL SIGN CANDRA O 0ACB..0ACC ; SpacingMark # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU 0B02..0B03 ; SpacingMark # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA 0B40 ; SpacingMark # Mc ORIYA VOWEL SIGN II 0B47..0B48 ; SpacingMark # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI 0B4B..0B4C ; SpacingMark # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU 0BBF ; SpacingMark # Mc TAMIL VOWEL SIGN I 0BC1..0BC2 ; SpacingMark # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU 0BC6..0BC8 ; SpacingMark # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI 0BCA..0BCC ; SpacingMark # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU 0C01..0C03 ; SpacingMark # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA 0C41..0C44 ; SpacingMark # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR 0C82..0C83 ; SpacingMark # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA 0CBE ; SpacingMark # Mc KANNADA VOWEL SIGN AA 0CC0..0CC1 ; SpacingMark # Mc [2] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN U 0CC3..0CC4 ; SpacingMark # Mc [2] KANNADA VOWEL SIGN VOCALIC R..KANNADA VOWEL SIGN VOCALIC RR 0CC7..0CC8 ; SpacingMark # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI 0CCA..0CCB ; SpacingMark # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO 0D02..0D03 ; SpacingMark # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA 0D3F..0D40 ; SpacingMark # Mc [2] MALAYALAM VOWEL SIGN I..MALAYALAM VOWEL SIGN II 0D46..0D48 ; SpacingMark # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI 0D4A..0D4C ; SpacingMark # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU 0D82..0D83 ; SpacingMark # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA 0DD0..0DD1 ; SpacingMark # Mc [2] SINHALA VOWEL SIGN KETTI AEDA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA 0DD8..0DDE ; SpacingMark # Mc [7] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA 0DF2..0DF3 ; SpacingMark # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA 0E33 ; SpacingMark # Lo THAI CHARACTER SARA AM 0EB3 ; SpacingMark # Lo LAO VOWEL SIGN AM 0F3E..0F3F ; SpacingMark # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES 0F7F ; SpacingMark # Mc TIBETAN SIGN RNAM BCAD 1031 ; SpacingMark # Mc MYANMAR VOWEL SIGN E 103B..103C ; SpacingMark # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA 1056..1057 ; SpacingMark # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR 1084 ; SpacingMark # Mc MYANMAR VOWEL SIGN SHAN E 17B6 ; SpacingMark # Mc KHMER VOWEL SIGN AA 17BE..17C5 ; SpacingMark # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU 17C7..17C8 ; SpacingMark # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU 1923..1926 ; SpacingMark # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU 1929..192B ; SpacingMark # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA 1930..1931 ; SpacingMark # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA 1933..1938 ; SpacingMark # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA 19B5..19B7 ; SpacingMark # Mc [3] NEW TAI LUE VOWEL SIGN E..NEW TAI LUE VOWEL SIGN O 19BA ; SpacingMark # Mc NEW TAI LUE VOWEL SIGN AY 1A19..1A1A ; SpacingMark # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O 1A55 ; SpacingMark # Mc TAI THAM CONSONANT SIGN MEDIAL RA 1A57 ; SpacingMark # Mc TAI THAM CONSONANT SIGN LA TANG LAI 1A6D..1A72 ; SpacingMark # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI 1B04 ; SpacingMark # Mc BALINESE SIGN BISAH 1B35 ; SpacingMark # Mc BALINESE VOWEL SIGN TEDUNG 1B3B ; SpacingMark # Mc BALINESE VOWEL SIGN RA REPA TEDUNG 1B3D..1B41 ; SpacingMark # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG 1B43..1B44 ; SpacingMark # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG 1B82 ; SpacingMark # Mc SUNDANESE SIGN PANGWISAD 1BA1 ; SpacingMark # Mc SUNDANESE CONSONANT SIGN PAMINGKAL 1BA6..1BA7 ; SpacingMark # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG 1BAA ; SpacingMark # Mc SUNDANESE SIGN PAMAAEH 1BE7 ; SpacingMark # Mc BATAK VOWEL SIGN E 1BEA..1BEC ; SpacingMark # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O 1BEE ; SpacingMark # Mc BATAK VOWEL SIGN U 1BF2..1BF3 ; SpacingMark # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN 1C24..1C2B ; SpacingMark # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU 1C34..1C35 ; SpacingMark # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG 1CE1 ; SpacingMark # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA 1CF2..1CF3 ; SpacingMark # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA A823..A824 ; SpacingMark # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I A827 ; SpacingMark # Mc SYLOTI NAGRI VOWEL SIGN OO A880..A881 ; SpacingMark # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA A8B4..A8C3 ; SpacingMark # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU A952..A953 ; SpacingMark # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA A983 ; SpacingMark # Mc JAVANESE SIGN WIGNYAN A9B4..A9B5 ; SpacingMark # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG A9BA..A9BB ; SpacingMark # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE A9BD..A9C0 ; SpacingMark # Mc [4] JAVANESE CONSONANT SIGN KERET..JAVANESE PANGKON AA2F..AA30 ; SpacingMark # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI AA33..AA34 ; SpacingMark # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA AA4D ; SpacingMark # Mc CHAM CONSONANT SIGN FINAL H AAEB ; SpacingMark # Mc MEETEI MAYEK VOWEL SIGN II AAEE..AAEF ; SpacingMark # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU AAF5 ; SpacingMark # Mc MEETEI MAYEK VOWEL SIGN VISARGA ABE3..ABE4 ; SpacingMark # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP ABE6..ABE7 ; SpacingMark # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP ABE9..ABEA ; SpacingMark # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK 11000 ; SpacingMark # Mc BRAHMI SIGN CANDRABINDU 11002 ; SpacingMark # Mc BRAHMI SIGN VISARGA 11082 ; SpacingMark # Mc KAITHI SIGN VISARGA 110B0..110B2 ; SpacingMark # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II 110B7..110B8 ; SpacingMark # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU 1112C ; SpacingMark # Mc CHAKMA VOWEL SIGN E 11182 ; SpacingMark # Mc SHARADA SIGN VISARGA 111B3..111B5 ; SpacingMark # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II 111BF..111C0 ; SpacingMark # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA 1122C..1122E ; SpacingMark # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II 11232..11233 ; SpacingMark # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU 11235 ; SpacingMark # Mc KHOJKI SIGN VIRAMA 112E0..112E2 ; SpacingMark # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II 11302..11303 ; SpacingMark # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA 1133F ; SpacingMark # Mc GRANTHA VOWEL SIGN I 11341..11344 ; SpacingMark # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR 11347..11348 ; SpacingMark # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI 1134B..1134D ; SpacingMark # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA 11362..11363 ; SpacingMark # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL 114B1..114B2 ; SpacingMark # Mc [2] TIRHUTA VOWEL SIGN I..TIRHUTA VOWEL SIGN II 114B9 ; SpacingMark # Mc TIRHUTA VOWEL SIGN E 114BB..114BC ; SpacingMark # Mc [2] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN O 114BE ; SpacingMark # Mc TIRHUTA VOWEL SIGN AU 114C1 ; SpacingMark # Mc TIRHUTA SIGN VISARGA 115B0..115B1 ; SpacingMark # Mc [2] SIDDHAM VOWEL SIGN I..SIDDHAM VOWEL SIGN II 115B8..115BB ; SpacingMark # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU 115BE ; SpacingMark # Mc SIDDHAM SIGN VISARGA 11630..11632 ; SpacingMark # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II 1163B..1163C ; SpacingMark # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU 1163E ; SpacingMark # Mc MODI SIGN VISARGA 116AC ; SpacingMark # Mc TAKRI SIGN VISARGA 116AE..116AF ; SpacingMark # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II 116B6 ; SpacingMark # Mc TAKRI SIGN VIRAMA 16F51..16F7E ; SpacingMark # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG 1D166 ; SpacingMark # Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM 1D16D ; SpacingMark # Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT 1100..115F ; L # Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER A960..A97C ; L # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH 1160..11A7 ; V # Lo [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE D7B0..D7C6 ; V # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E 11A8..11FF ; T # Lo [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN D7CB..D7FB ; T # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH AC00 ; LV # Lo HANGUL SYLLABLE GA AC1C ; LV # Lo HANGUL SYLLABLE GAE AC38 ; LV # Lo HANGUL SYLLABLE GYA AC54 ; LV # Lo HANGUL SYLLABLE GYAE AC70 ; LV # Lo HANGUL SYLLABLE GEO AC8C ; LV # Lo HANGUL SYLLABLE GE ACA8 ; LV # Lo HANGUL SYLLABLE GYEO ACC4 ; LV # Lo HANGUL SYLLABLE GYE ACE0 ; LV # Lo HANGUL SYLLABLE GO ACFC ; LV # Lo HANGUL SYLLABLE GWA AD18 ; LV # Lo HANGUL SYLLABLE GWAE AD34 ; LV # Lo HANGUL SYLLABLE GOE AD50 ; LV # Lo HANGUL SYLLABLE GYO AD6C ; LV # Lo HANGUL SYLLABLE GU AD88 ; LV # Lo HANGUL SYLLABLE GWEO ADA4 ; LV # Lo HANGUL SYLLABLE GWE ADC0 ; LV # Lo HANGUL SYLLABLE GWI ADDC ; LV # Lo HANGUL SYLLABLE GYU ADF8 ; LV # Lo HANGUL SYLLABLE GEU AE14 ; LV # Lo HANGUL SYLLABLE GYI AE30 ; LV # Lo HANGUL SYLLABLE GI AE4C ; LV # Lo HANGUL SYLLABLE GGA AE68 ; LV # Lo HANGUL SYLLABLE GGAE AE84 ; LV # Lo HANGUL SYLLABLE GGYA AEA0 ; LV # Lo HANGUL SYLLABLE GGYAE AEBC ; LV # Lo HANGUL SYLLABLE GGEO AED8 ; LV # Lo HANGUL SYLLABLE GGE AEF4 ; LV # Lo HANGUL SYLLABLE GGYEO AF10 ; LV # Lo HANGUL SYLLABLE GGYE AF2C ; LV # Lo HANGUL SYLLABLE GGO AF48 ; LV # Lo HANGUL SYLLABLE GGWA AF64 ; LV # Lo HANGUL SYLLABLE GGWAE AF80 ; LV # Lo HANGUL SYLLABLE GGOE AF9C ; LV # Lo HANGUL SYLLABLE GGYO AFB8 ; LV # Lo HANGUL SYLLABLE GGU AFD4 ; LV # Lo HANGUL SYLLABLE GGWEO AFF0 ; LV # Lo HANGUL SYLLABLE GGWE B00C ; LV # Lo HANGUL SYLLABLE GGWI B028 ; LV # Lo HANGUL SYLLABLE GGYU B044 ; LV # Lo HANGUL SYLLABLE GGEU B060 ; LV # Lo HANGUL SYLLABLE GGYI B07C ; LV # Lo HANGUL SYLLABLE GGI B098 ; LV # Lo HANGUL SYLLABLE NA B0B4 ; LV # Lo HANGUL SYLLABLE NAE B0D0 ; LV # Lo HANGUL SYLLABLE NYA B0EC ; LV # Lo HANGUL SYLLABLE NYAE B108 ; LV # Lo HANGUL SYLLABLE NEO B124 ; LV # Lo HANGUL SYLLABLE NE B140 ; LV # Lo HANGUL SYLLABLE NYEO B15C ; LV # Lo HANGUL SYLLABLE NYE B178 ; LV # Lo HANGUL SYLLABLE NO B194 ; LV # Lo HANGUL SYLLABLE NWA B1B0 ; LV # Lo HANGUL SYLLABLE NWAE B1CC ; LV # Lo HANGUL SYLLABLE NOE B1E8 ; LV # Lo HANGUL SYLLABLE NYO B204 ; LV # Lo HANGUL SYLLABLE NU B220 ; LV # Lo HANGUL SYLLABLE NWEO B23C ; LV # Lo HANGUL SYLLABLE NWE B258 ; LV # Lo HANGUL SYLLABLE NWI B274 ; LV # Lo HANGUL SYLLABLE NYU B290 ; LV # Lo HANGUL SYLLABLE NEU B2AC ; LV # Lo HANGUL SYLLABLE NYI B2C8 ; LV # Lo HANGUL SYLLABLE NI B2E4 ; LV # Lo HANGUL SYLLABLE DA B300 ; LV # Lo HANGUL SYLLABLE DAE B31C ; LV # Lo HANGUL SYLLABLE DYA B338 ; LV # Lo HANGUL SYLLABLE DYAE B354 ; LV # Lo HANGUL SYLLABLE DEO B370 ; LV # Lo HANGUL SYLLABLE DE B38C ; LV # Lo HANGUL SYLLABLE DYEO B3A8 ; LV # Lo HANGUL SYLLABLE DYE B3C4 ; LV # Lo HANGUL SYLLABLE DO B3E0 ; LV # Lo HANGUL SYLLABLE DWA B3FC ; LV # Lo HANGUL SYLLABLE DWAE B418 ; LV # Lo HANGUL SYLLABLE DOE B434 ; LV # Lo HANGUL SYLLABLE DYO B450 ; LV # Lo HANGUL SYLLABLE DU B46C ; LV # Lo HANGUL SYLLABLE DWEO B488 ; LV # Lo HANGUL SYLLABLE DWE B4A4 ; LV # Lo HANGUL SYLLABLE DWI B4C0 ; LV # Lo HANGUL SYLLABLE DYU B4DC ; LV # Lo HANGUL SYLLABLE DEU B4F8 ; LV # Lo HANGUL SYLLABLE DYI B514 ; LV # Lo HANGUL SYLLABLE DI B530 ; LV # Lo HANGUL SYLLABLE DDA B54C ; LV # Lo HANGUL SYLLABLE DDAE B568 ; LV # Lo HANGUL SYLLABLE DDYA B584 ; LV # Lo HANGUL SYLLABLE DDYAE B5A0 ; LV # Lo HANGUL SYLLABLE DDEO B5BC ; LV # Lo HANGUL SYLLABLE DDE B5D8 ; LV # Lo HANGUL SYLLABLE DDYEO B5F4 ; LV # Lo HANGUL SYLLABLE DDYE B610 ; LV # Lo HANGUL SYLLABLE DDO B62C ; LV # Lo HANGUL SYLLABLE DDWA B648 ; LV # Lo HANGUL SYLLABLE DDWAE B664 ; LV # Lo HANGUL SYLLABLE DDOE B680 ; LV # Lo HANGUL SYLLABLE DDYO B69C ; LV # Lo HANGUL SYLLABLE DDU B6B8 ; LV # Lo HANGUL SYLLABLE DDWEO B6D4 ; LV # Lo HANGUL SYLLABLE DDWE B6F0 ; LV # Lo HANGUL SYLLABLE DDWI B70C ; LV # Lo HANGUL SYLLABLE DDYU B728 ; LV # Lo HANGUL SYLLABLE DDEU B744 ; LV # Lo HANGUL SYLLABLE DDYI B760 ; LV # Lo HANGUL SYLLABLE DDI B77C ; LV # Lo HANGUL SYLLABLE RA B798 ; LV # Lo HANGUL SYLLABLE RAE B7B4 ; LV # Lo HANGUL SYLLABLE RYA B7D0 ; LV # Lo HANGUL SYLLABLE RYAE B7EC ; LV # Lo HANGUL SYLLABLE REO B808 ; LV # Lo HANGUL SYLLABLE RE B824 ; LV # Lo HANGUL SYLLABLE RYEO B840 ; LV # Lo HANGUL SYLLABLE RYE B85C ; LV # Lo HANGUL SYLLABLE RO B878 ; LV # Lo HANGUL SYLLABLE RWA B894 ; LV # Lo HANGUL SYLLABLE RWAE B8B0 ; LV # Lo HANGUL SYLLABLE ROE B8CC ; LV # Lo HANGUL SYLLABLE RYO B8E8 ; LV # Lo HANGUL SYLLABLE RU B904 ; LV # Lo HANGUL SYLLABLE RWEO B920 ; LV # Lo HANGUL SYLLABLE RWE B93C ; LV # Lo HANGUL SYLLABLE RWI B958 ; LV # Lo HANGUL SYLLABLE RYU B974 ; LV # Lo HANGUL SYLLABLE REU B990 ; LV # Lo HANGUL SYLLABLE RYI B9AC ; LV # Lo HANGUL SYLLABLE RI B9C8 ; LV # Lo HANGUL SYLLABLE MA B9E4 ; LV # Lo HANGUL SYLLABLE MAE BA00 ; LV # Lo HANGUL SYLLABLE MYA BA1C ; LV # Lo HANGUL SYLLABLE MYAE BA38 ; LV # Lo HANGUL SYLLABLE MEO BA54 ; LV # Lo HANGUL SYLLABLE ME BA70 ; LV # Lo HANGUL SYLLABLE MYEO BA8C ; LV # Lo HANGUL SYLLABLE MYE BAA8 ; LV # Lo HANGUL SYLLABLE MO BAC4 ; LV # Lo HANGUL SYLLABLE MWA BAE0 ; LV # Lo HANGUL SYLLABLE MWAE BAFC ; LV # Lo HANGUL SYLLABLE MOE BB18 ; LV # Lo HANGUL SYLLABLE MYO BB34 ; LV # Lo HANGUL SYLLABLE MU BB50 ; LV # Lo HANGUL SYLLABLE MWEO BB6C ; LV # Lo HANGUL SYLLABLE MWE BB88 ; LV # Lo HANGUL SYLLABLE MWI BBA4 ; LV # Lo HANGUL SYLLABLE MYU BBC0 ; LV # Lo HANGUL SYLLABLE MEU BBDC ; LV # Lo HANGUL SYLLABLE MYI BBF8 ; LV # Lo HANGUL SYLLABLE MI BC14 ; LV # Lo HANGUL SYLLABLE BA BC30 ; LV # Lo HANGUL SYLLABLE BAE BC4C ; LV # Lo HANGUL SYLLABLE BYA BC68 ; LV # Lo HANGUL SYLLABLE BYAE BC84 ; LV # Lo HANGUL SYLLABLE BEO BCA0 ; LV # Lo HANGUL SYLLABLE BE BCBC ; LV # Lo HANGUL SYLLABLE BYEO BCD8 ; LV # Lo HANGUL SYLLABLE BYE BCF4 ; LV # Lo HANGUL SYLLABLE BO BD10 ; LV # Lo HANGUL SYLLABLE BWA BD2C ; LV # Lo HANGUL SYLLABLE BWAE BD48 ; LV # Lo HANGUL SYLLABLE BOE BD64 ; LV # Lo HANGUL SYLLABLE BYO BD80 ; LV # Lo HANGUL SYLLABLE BU BD9C ; LV # Lo HANGUL SYLLABLE BWEO BDB8 ; LV # Lo HANGUL SYLLABLE BWE BDD4 ; LV # Lo HANGUL SYLLABLE BWI BDF0 ; LV # Lo HANGUL SYLLABLE BYU BE0C ; LV # Lo HANGUL SYLLABLE BEU BE28 ; LV # Lo HANGUL SYLLABLE BYI BE44 ; LV # Lo HANGUL SYLLABLE BI BE60 ; LV # Lo HANGUL SYLLABLE BBA BE7C ; LV # Lo HANGUL SYLLABLE BBAE BE98 ; LV # Lo HANGUL SYLLABLE BBYA BEB4 ; LV # Lo HANGUL SYLLABLE BBYAE BED0 ; LV # Lo HANGUL SYLLABLE BBEO BEEC ; LV # Lo HANGUL SYLLABLE BBE BF08 ; LV # Lo HANGUL SYLLABLE BBYEO BF24 ; LV # Lo HANGUL SYLLABLE BBYE BF40 ; LV # Lo HANGUL SYLLABLE BBO BF5C ; LV # Lo HANGUL SYLLABLE BBWA BF78 ; LV # Lo HANGUL SYLLABLE BBWAE BF94 ; LV # Lo HANGUL SYLLABLE BBOE BFB0 ; LV # Lo HANGUL SYLLABLE BBYO BFCC ; LV # Lo HANGUL SYLLABLE BBU BFE8 ; LV # Lo HANGUL SYLLABLE BBWEO C004 ; LV # Lo HANGUL SYLLABLE BBWE C020 ; LV # Lo HANGUL SYLLABLE BBWI C03C ; LV # Lo HANGUL SYLLABLE BBYU C058 ; LV # Lo HANGUL SYLLABLE BBEU C074 ; LV # Lo HANGUL SYLLABLE BBYI C090 ; LV # Lo HANGUL SYLLABLE BBI C0AC ; LV # Lo HANGUL SYLLABLE SA C0C8 ; LV # Lo HANGUL SYLLABLE SAE C0E4 ; LV # Lo HANGUL SYLLABLE SYA C100 ; LV # Lo HANGUL SYLLABLE SYAE C11C ; LV # Lo HANGUL SYLLABLE SEO C138 ; LV # Lo HANGUL SYLLABLE SE C154 ; LV # Lo HANGUL SYLLABLE SYEO C170 ; LV # Lo HANGUL SYLLABLE SYE C18C ; LV # Lo HANGUL SYLLABLE SO C1A8 ; LV # Lo HANGUL SYLLABLE SWA C1C4 ; LV # Lo HANGUL SYLLABLE SWAE C1E0 ; LV # Lo HANGUL SYLLABLE SOE C1FC ; LV # Lo HANGUL SYLLABLE SYO C218 ; LV # Lo HANGUL SYLLABLE SU C234 ; LV # Lo HANGUL SYLLABLE SWEO C250 ; LV # Lo HANGUL SYLLABLE SWE C26C ; LV # Lo HANGUL SYLLABLE SWI C288 ; LV # Lo HANGUL SYLLABLE SYU C2A4 ; LV # Lo HANGUL SYLLABLE SEU C2C0 ; LV # Lo HANGUL SYLLABLE SYI C2DC ; LV # Lo HANGUL SYLLABLE SI C2F8 ; LV # Lo HANGUL SYLLABLE SSA C314 ; LV # Lo HANGUL SYLLABLE SSAE C330 ; LV # Lo HANGUL SYLLABLE SSYA C34C ; LV # Lo HANGUL SYLLABLE SSYAE C368 ; LV # Lo HANGUL SYLLABLE SSEO C384 ; LV # Lo HANGUL SYLLABLE SSE C3A0 ; LV # Lo HANGUL SYLLABLE SSYEO C3BC ; LV # Lo HANGUL SYLLABLE SSYE C3D8 ; LV # Lo HANGUL SYLLABLE SSO C3F4 ; LV # Lo HANGUL SYLLABLE SSWA C410 ; LV # Lo HANGUL SYLLABLE SSWAE C42C ; LV # Lo HANGUL SYLLABLE SSOE C448 ; LV # Lo HANGUL SYLLABLE SSYO C464 ; LV # Lo HANGUL SYLLABLE SSU C480 ; LV # Lo HANGUL SYLLABLE SSWEO C49C ; LV # Lo HANGUL SYLLABLE SSWE C4B8 ; LV # Lo HANGUL SYLLABLE SSWI C4D4 ; LV # Lo HANGUL SYLLABLE SSYU C4F0 ; LV # Lo HANGUL SYLLABLE SSEU C50C ; LV # Lo HANGUL SYLLABLE SSYI C528 ; LV # Lo HANGUL SYLLABLE SSI C544 ; LV # Lo HANGUL SYLLABLE A C560 ; LV # Lo HANGUL SYLLABLE AE C57C ; LV # Lo HANGUL SYLLABLE YA C598 ; LV # Lo HANGUL SYLLABLE YAE C5B4 ; LV # Lo HANGUL SYLLABLE EO C5D0 ; LV # Lo HANGUL SYLLABLE E C5EC ; LV # Lo HANGUL SYLLABLE YEO C608 ; LV # Lo HANGUL SYLLABLE YE C624 ; LV # Lo HANGUL SYLLABLE O C640 ; LV # Lo HANGUL SYLLABLE WA C65C ; LV # Lo HANGUL SYLLABLE WAE C678 ; LV # Lo HANGUL SYLLABLE OE C694 ; LV # Lo HANGUL SYLLABLE YO C6B0 ; LV # Lo HANGUL SYLLABLE U C6CC ; LV # Lo HANGUL SYLLABLE WEO C6E8 ; LV # Lo HANGUL SYLLABLE WE C704 ; LV # Lo HANGUL SYLLABLE WI C720 ; LV # Lo HANGUL SYLLABLE YU C73C ; LV # Lo HANGUL SYLLABLE EU C758 ; LV # Lo HANGUL SYLLABLE YI C774 ; LV # Lo HANGUL SYLLABLE I C790 ; LV # Lo HANGUL SYLLABLE JA C7AC ; LV # Lo HANGUL SYLLABLE JAE C7C8 ; LV # Lo HANGUL SYLLABLE JYA C7E4 ; LV # Lo HANGUL SYLLABLE JYAE C800 ; LV # Lo HANGUL SYLLABLE JEO C81C ; LV # Lo HANGUL SYLLABLE JE C838 ; LV # Lo HANGUL SYLLABLE JYEO C854 ; LV # Lo HANGUL SYLLABLE JYE C870 ; LV # Lo HANGUL SYLLABLE JO C88C ; LV # Lo HANGUL SYLLABLE JWA C8A8 ; LV # Lo HANGUL SYLLABLE JWAE C8C4 ; LV # Lo HANGUL SYLLABLE JOE C8E0 ; LV # Lo HANGUL SYLLABLE JYO C8FC ; LV # Lo HANGUL SYLLABLE JU C918 ; LV # Lo HANGUL SYLLABLE JWEO C934 ; LV # Lo HANGUL SYLLABLE JWE C950 ; LV # Lo HANGUL SYLLABLE JWI C96C ; LV # Lo HANGUL SYLLABLE JYU C988 ; LV # Lo HANGUL SYLLABLE JEU C9A4 ; LV # Lo HANGUL SYLLABLE JYI C9C0 ; LV # Lo HANGUL SYLLABLE JI C9DC ; LV # Lo HANGUL SYLLABLE JJA C9F8 ; LV # Lo HANGUL SYLLABLE JJAE CA14 ; LV # Lo HANGUL SYLLABLE JJYA CA30 ; LV # Lo HANGUL SYLLABLE JJYAE CA4C ; LV # Lo HANGUL SYLLABLE JJEO CA68 ; LV # Lo HANGUL SYLLABLE JJE CA84 ; LV # Lo HANGUL SYLLABLE JJYEO CAA0 ; LV # Lo HANGUL SYLLABLE JJYE CABC ; LV # Lo HANGUL SYLLABLE JJO CAD8 ; LV # Lo HANGUL SYLLABLE JJWA CAF4 ; LV # Lo HANGUL SYLLABLE JJWAE CB10 ; LV # Lo HANGUL SYLLABLE JJOE CB2C ; LV # Lo HANGUL SYLLABLE JJYO CB48 ; LV # Lo HANGUL SYLLABLE JJU CB64 ; LV # Lo HANGUL SYLLABLE JJWEO CB80 ; LV # Lo HANGUL SYLLABLE JJWE CB9C ; LV # Lo HANGUL SYLLABLE JJWI CBB8 ; LV # Lo HANGUL SYLLABLE JJYU CBD4 ; LV # Lo HANGUL SYLLABLE JJEU CBF0 ; LV # Lo HANGUL SYLLABLE JJYI CC0C ; LV # Lo HANGUL SYLLABLE JJI CC28 ; LV # Lo HANGUL SYLLABLE CA CC44 ; LV # Lo HANGUL SYLLABLE CAE CC60 ; LV # Lo HANGUL SYLLABLE CYA CC7C ; LV # Lo HANGUL SYLLABLE CYAE CC98 ; LV # Lo HANGUL SYLLABLE CEO CCB4 ; LV # Lo HANGUL SYLLABLE CE CCD0 ; LV # Lo HANGUL SYLLABLE CYEO CCEC ; LV # Lo HANGUL SYLLABLE CYE CD08 ; LV # Lo HANGUL SYLLABLE CO CD24 ; LV # Lo HANGUL SYLLABLE CWA CD40 ; LV # Lo HANGUL SYLLABLE CWAE CD5C ; LV # Lo HANGUL SYLLABLE COE CD78 ; LV # Lo HANGUL SYLLABLE CYO CD94 ; LV # Lo HANGUL SYLLABLE CU CDB0 ; LV # Lo HANGUL SYLLABLE CWEO CDCC ; LV # Lo HANGUL SYLLABLE CWE CDE8 ; LV # Lo HANGUL SYLLABLE CWI CE04 ; LV # Lo HANGUL SYLLABLE CYU CE20 ; LV # Lo HANGUL SYLLABLE CEU CE3C ; LV # Lo HANGUL SYLLABLE CYI CE58 ; LV # Lo HANGUL SYLLABLE CI CE74 ; LV # Lo HANGUL SYLLABLE KA CE90 ; LV # Lo HANGUL SYLLABLE KAE CEAC ; LV # Lo HANGUL SYLLABLE KYA CEC8 ; LV # Lo HANGUL SYLLABLE KYAE CEE4 ; LV # Lo HANGUL SYLLABLE KEO CF00 ; LV # Lo HANGUL SYLLABLE KE CF1C ; LV # Lo HANGUL SYLLABLE KYEO CF38 ; LV # Lo HANGUL SYLLABLE KYE CF54 ; LV # Lo HANGUL SYLLABLE KO CF70 ; LV # Lo HANGUL SYLLABLE KWA CF8C ; LV # Lo HANGUL SYLLABLE KWAE CFA8 ; LV # Lo HANGUL SYLLABLE KOE CFC4 ; LV # Lo HANGUL SYLLABLE KYO CFE0 ; LV # Lo HANGUL SYLLABLE KU CFFC ; LV # Lo HANGUL SYLLABLE KWEO D018 ; LV # Lo HANGUL SYLLABLE KWE D034 ; LV # Lo HANGUL SYLLABLE KWI D050 ; LV # Lo HANGUL SYLLABLE KYU D06C ; LV # Lo HANGUL SYLLABLE KEU D088 ; LV # Lo HANGUL SYLLABLE KYI D0A4 ; LV # Lo HANGUL SYLLABLE KI D0C0 ; LV # Lo HANGUL SYLLABLE TA D0DC ; LV # Lo HANGUL SYLLABLE TAE D0F8 ; LV # Lo HANGUL SYLLABLE TYA D114 ; LV # Lo HANGUL SYLLABLE TYAE D130 ; LV # Lo HANGUL SYLLABLE TEO D14C ; LV # Lo HANGUL SYLLABLE TE D168 ; LV # Lo HANGUL SYLLABLE TYEO D184 ; LV # Lo HANGUL SYLLABLE TYE D1A0 ; LV # Lo HANGUL SYLLABLE TO D1BC ; LV # Lo HANGUL SYLLABLE TWA D1D8 ; LV # Lo HANGUL SYLLABLE TWAE D1F4 ; LV # Lo HANGUL SYLLABLE TOE D210 ; LV # Lo HANGUL SYLLABLE TYO D22C ; LV # Lo HANGUL SYLLABLE TU D248 ; LV # Lo HANGUL SYLLABLE TWEO D264 ; LV # Lo HANGUL SYLLABLE TWE D280 ; LV # Lo HANGUL SYLLABLE TWI D29C ; LV # Lo HANGUL SYLLABLE TYU D2B8 ; LV # Lo HANGUL SYLLABLE TEU D2D4 ; LV # Lo HANGUL SYLLABLE TYI D2F0 ; LV # Lo HANGUL SYLLABLE TI D30C ; LV # Lo HANGUL SYLLABLE PA D328 ; LV # Lo HANGUL SYLLABLE PAE D344 ; LV # Lo HANGUL SYLLABLE PYA D360 ; LV # Lo HANGUL SYLLABLE PYAE D37C ; LV # Lo HANGUL SYLLABLE PEO D398 ; LV # Lo HANGUL SYLLABLE PE D3B4 ; LV # Lo HANGUL SYLLABLE PYEO D3D0 ; LV # Lo HANGUL SYLLABLE PYE D3EC ; LV # Lo HANGUL SYLLABLE PO D408 ; LV # Lo HANGUL SYLLABLE PWA D424 ; LV # Lo HANGUL SYLLABLE PWAE D440 ; LV # Lo HANGUL SYLLABLE POE D45C ; LV # Lo HANGUL SYLLABLE PYO D478 ; LV # Lo HANGUL SYLLABLE PU D494 ; LV # Lo HANGUL SYLLABLE PWEO D4B0 ; LV # Lo HANGUL SYLLABLE PWE D4CC ; LV # Lo HANGUL SYLLABLE PWI D4E8 ; LV # Lo HANGUL SYLLABLE PYU D504 ; LV # Lo HANGUL SYLLABLE PEU D520 ; LV # Lo HANGUL SYLLABLE PYI D53C ; LV # Lo HANGUL SYLLABLE PI D558 ; LV # Lo HANGUL SYLLABLE HA D574 ; LV # Lo HANGUL SYLLABLE HAE D590 ; LV # Lo HANGUL SYLLABLE HYA D5AC ; LV # Lo HANGUL SYLLABLE HYAE D5C8 ; LV # Lo HANGUL SYLLABLE HEO D5E4 ; LV # Lo HANGUL SYLLABLE HE D600 ; LV # Lo HANGUL SYLLABLE HYEO D61C ; LV # Lo HANGUL SYLLABLE HYE D638 ; LV # Lo HANGUL SYLLABLE HO D654 ; LV # Lo HANGUL SYLLABLE HWA D670 ; LV # Lo HANGUL SYLLABLE HWAE D68C ; LV # Lo HANGUL SYLLABLE HOE D6A8 ; LV # Lo HANGUL SYLLABLE HYO D6C4 ; LV # Lo HANGUL SYLLABLE HU D6E0 ; LV # Lo HANGUL SYLLABLE HWEO D6FC ; LV # Lo HANGUL SYLLABLE HWE D718 ; LV # Lo HANGUL SYLLABLE HWI D734 ; LV # Lo HANGUL SYLLABLE HYU D750 ; LV # Lo HANGUL SYLLABLE HEU D76C ; LV # Lo HANGUL SYLLABLE HYI D788 ; LV # Lo HANGUL SYLLABLE HI AC01..AC1B ; LVT # Lo [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH AC1D..AC37 ; LVT # Lo [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH AC39..AC53 ; LVT # Lo [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH AC55..AC6F ; LVT # Lo [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH AC71..AC8B ; LVT # Lo [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH AC8D..ACA7 ; LVT # Lo [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH ACA9..ACC3 ; LVT # Lo [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH ACC5..ACDF ; LVT # Lo [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH ACE1..ACFB ; LVT # Lo [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH ACFD..AD17 ; LVT # Lo [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH AD19..AD33 ; LVT # Lo [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH AD35..AD4F ; LVT # Lo [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH AD51..AD6B ; LVT # Lo [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH AD6D..AD87 ; LVT # Lo [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH AD89..ADA3 ; LVT # Lo [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH ADA5..ADBF ; LVT # Lo [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH ADC1..ADDB ; LVT # Lo [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH ADDD..ADF7 ; LVT # Lo [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH ADF9..AE13 ; LVT # Lo [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH AE15..AE2F ; LVT # Lo [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH AE31..AE4B ; LVT # Lo [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH AE4D..AE67 ; LVT # Lo [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH AE69..AE83 ; LVT # Lo [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH AE85..AE9F ; LVT # Lo [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH AEA1..AEBB ; LVT # Lo [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH AEBD..AED7 ; LVT # Lo [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH AED9..AEF3 ; LVT # Lo [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH AEF5..AF0F ; LVT # Lo [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH AF11..AF2B ; LVT # Lo [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH AF2D..AF47 ; LVT # Lo [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH AF49..AF63 ; LVT # Lo [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH AF65..AF7F ; LVT # Lo [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH AF81..AF9B ; LVT # Lo [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH AF9D..AFB7 ; LVT # Lo [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH AFB9..AFD3 ; LVT # Lo [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH AFD5..AFEF ; LVT # Lo [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH AFF1..B00B ; LVT # Lo [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH B00D..B027 ; LVT # Lo [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH B029..B043 ; LVT # Lo [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH B045..B05F ; LVT # Lo [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH B061..B07B ; LVT # Lo [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH B07D..B097 ; LVT # Lo [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH B099..B0B3 ; LVT # Lo [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH B0B5..B0CF ; LVT # Lo [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH B0D1..B0EB ; LVT # Lo [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH B0ED..B107 ; LVT # Lo [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH B109..B123 ; LVT # Lo [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH B125..B13F ; LVT # Lo [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH B141..B15B ; LVT # Lo [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH B15D..B177 ; LVT # Lo [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH B179..B193 ; LVT # Lo [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH B195..B1AF ; LVT # Lo [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH B1B1..B1CB ; LVT # Lo [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH B1CD..B1E7 ; LVT # Lo [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH B1E9..B203 ; LVT # Lo [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH B205..B21F ; LVT # Lo [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH B221..B23B ; LVT # Lo [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH B23D..B257 ; LVT # Lo [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH B259..B273 ; LVT # Lo [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH B275..B28F ; LVT # Lo [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH B291..B2AB ; LVT # Lo [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH B2AD..B2C7 ; LVT # Lo [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH B2C9..B2E3 ; LVT # Lo [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH B2E5..B2FF ; LVT # Lo [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH B301..B31B ; LVT # Lo [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH B31D..B337 ; LVT # Lo [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH B339..B353 ; LVT # Lo [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH B355..B36F ; LVT # Lo [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH B371..B38B ; LVT # Lo [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH B38D..B3A7 ; LVT # Lo [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH B3A9..B3C3 ; LVT # Lo [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH B3C5..B3DF ; LVT # Lo [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH B3E1..B3FB ; LVT # Lo [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH B3FD..B417 ; LVT # Lo [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH B419..B433 ; LVT # Lo [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH B435..B44F ; LVT # Lo [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH B451..B46B ; LVT # Lo [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH B46D..B487 ; LVT # Lo [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH B489..B4A3 ; LVT # Lo [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH B4A5..B4BF ; LVT # Lo [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH B4C1..B4DB ; LVT # Lo [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH B4DD..B4F7 ; LVT # Lo [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH B4F9..B513 ; LVT # Lo [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH B515..B52F ; LVT # Lo [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH B531..B54B ; LVT # Lo [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH B54D..B567 ; LVT # Lo [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH B569..B583 ; LVT # Lo [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH B585..B59F ; LVT # Lo [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH B5A1..B5BB ; LVT # Lo [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH B5BD..B5D7 ; LVT # Lo [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH B5D9..B5F3 ; LVT # Lo [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH B5F5..B60F ; LVT # Lo [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH B611..B62B ; LVT # Lo [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH B62D..B647 ; LVT # Lo [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH B649..B663 ; LVT # Lo [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH B665..B67F ; LVT # Lo [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH B681..B69B ; LVT # Lo [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH B69D..B6B7 ; LVT # Lo [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH B6B9..B6D3 ; LVT # Lo [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH B6D5..B6EF ; LVT # Lo [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH B6F1..B70B ; LVT # Lo [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH B70D..B727 ; LVT # Lo [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH B729..B743 ; LVT # Lo [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH B745..B75F ; LVT # Lo [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH B761..B77B ; LVT # Lo [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH B77D..B797 ; LVT # Lo [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH B799..B7B3 ; LVT # Lo [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH B7B5..B7CF ; LVT # Lo [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH B7D1..B7EB ; LVT # Lo [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH B7ED..B807 ; LVT # Lo [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH B809..B823 ; LVT # Lo [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH B825..B83F ; LVT # Lo [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH B841..B85B ; LVT # Lo [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH B85D..B877 ; LVT # Lo [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH B879..B893 ; LVT # Lo [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH B895..B8AF ; LVT # Lo [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH B8B1..B8CB ; LVT # Lo [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH B8CD..B8E7 ; LVT # Lo [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH B8E9..B903 ; LVT # Lo [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH B905..B91F ; LVT # Lo [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH B921..B93B ; LVT # Lo [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH B93D..B957 ; LVT # Lo [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH B959..B973 ; LVT # Lo [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH B975..B98F ; LVT # Lo [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH B991..B9AB ; LVT # Lo [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH B9AD..B9C7 ; LVT # Lo [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH B9C9..B9E3 ; LVT # Lo [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH B9E5..B9FF ; LVT # Lo [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH BA01..BA1B ; LVT # Lo [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH BA1D..BA37 ; LVT # Lo [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH BA39..BA53 ; LVT # Lo [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH BA55..BA6F ; LVT # Lo [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH BA71..BA8B ; LVT # Lo [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH BA8D..BAA7 ; LVT # Lo [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH BAA9..BAC3 ; LVT # Lo [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH BAC5..BADF ; LVT # Lo [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH BAE1..BAFB ; LVT # Lo [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH BAFD..BB17 ; LVT # Lo [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH BB19..BB33 ; LVT # Lo [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH BB35..BB4F ; LVT # Lo [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH BB51..BB6B ; LVT # Lo [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH BB6D..BB87 ; LVT # Lo [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH BB89..BBA3 ; LVT # Lo [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH BBA5..BBBF ; LVT # Lo [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH BBC1..BBDB ; LVT # Lo [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH BBDD..BBF7 ; LVT # Lo [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH BBF9..BC13 ; LVT # Lo [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH BC15..BC2F ; LVT # Lo [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH BC31..BC4B ; LVT # Lo [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH BC4D..BC67 ; LVT # Lo [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH BC69..BC83 ; LVT # Lo [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH BC85..BC9F ; LVT # Lo [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH BCA1..BCBB ; LVT # Lo [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH BCBD..BCD7 ; LVT # Lo [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH BCD9..BCF3 ; LVT # Lo [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH BCF5..BD0F ; LVT # Lo [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH BD11..BD2B ; LVT # Lo [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH BD2D..BD47 ; LVT # Lo [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH BD49..BD63 ; LVT # Lo [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH BD65..BD7F ; LVT # Lo [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH BD81..BD9B ; LVT # Lo [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH BD9D..BDB7 ; LVT # Lo [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH BDB9..BDD3 ; LVT # Lo [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH BDD5..BDEF ; LVT # Lo [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH BDF1..BE0B ; LVT # Lo [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH BE0D..BE27 ; LVT # Lo [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH BE29..BE43 ; LVT # Lo [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH BE45..BE5F ; LVT # Lo [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH BE61..BE7B ; LVT # Lo [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH BE7D..BE97 ; LVT # Lo [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH BE99..BEB3 ; LVT # Lo [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH BEB5..BECF ; LVT # Lo [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH BED1..BEEB ; LVT # Lo [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH BEED..BF07 ; LVT # Lo [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH BF09..BF23 ; LVT # Lo [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH BF25..BF3F ; LVT # Lo [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH BF41..BF5B ; LVT # Lo [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH BF5D..BF77 ; LVT # Lo [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH BF79..BF93 ; LVT # Lo [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH BF95..BFAF ; LVT # Lo [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH BFB1..BFCB ; LVT # Lo [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH BFCD..BFE7 ; LVT # Lo [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH BFE9..C003 ; LVT # Lo [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH C005..C01F ; LVT # Lo [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH C021..C03B ; LVT # Lo [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH C03D..C057 ; LVT # Lo [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH C059..C073 ; LVT # Lo [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH C075..C08F ; LVT # Lo [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH C091..C0AB ; LVT # Lo [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH C0AD..C0C7 ; LVT # Lo [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH C0C9..C0E3 ; LVT # Lo [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH C0E5..C0FF ; LVT # Lo [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH C101..C11B ; LVT # Lo [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH C11D..C137 ; LVT # Lo [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH C139..C153 ; LVT # Lo [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH C155..C16F ; LVT # Lo [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH C171..C18B ; LVT # Lo [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH C18D..C1A7 ; LVT # Lo [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH C1A9..C1C3 ; LVT # Lo [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH C1C5..C1DF ; LVT # Lo [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH C1E1..C1FB ; LVT # Lo [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH C1FD..C217 ; LVT # Lo [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH C219..C233 ; LVT # Lo [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH C235..C24F ; LVT # Lo [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH C251..C26B ; LVT # Lo [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH C26D..C287 ; LVT # Lo [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH C289..C2A3 ; LVT # Lo [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH C2A5..C2BF ; LVT # Lo [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH C2C1..C2DB ; LVT # Lo [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH C2DD..C2F7 ; LVT # Lo [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH C2F9..C313 ; LVT # Lo [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH C315..C32F ; LVT # Lo [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH C331..C34B ; LVT # Lo [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH C34D..C367 ; LVT # Lo [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH C369..C383 ; LVT # Lo [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH C385..C39F ; LVT # Lo [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH C3A1..C3BB ; LVT # Lo [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH C3BD..C3D7 ; LVT # Lo [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH C3D9..C3F3 ; LVT # Lo [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH C3F5..C40F ; LVT # Lo [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH C411..C42B ; LVT # Lo [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH C42D..C447 ; LVT # Lo [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH C449..C463 ; LVT # Lo [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH C465..C47F ; LVT # Lo [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH C481..C49B ; LVT # Lo [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH C49D..C4B7 ; LVT # Lo [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH C4B9..C4D3 ; LVT # Lo [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH C4D5..C4EF ; LVT # Lo [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH C4F1..C50B ; LVT # Lo [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH C50D..C527 ; LVT # Lo [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH C529..C543 ; LVT # Lo [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH C545..C55F ; LVT # Lo [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH C561..C57B ; LVT # Lo [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH C57D..C597 ; LVT # Lo [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH C599..C5B3 ; LVT # Lo [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH C5B5..C5CF ; LVT # Lo [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH C5D1..C5EB ; LVT # Lo [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH C5ED..C607 ; LVT # Lo [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH C609..C623 ; LVT # Lo [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH C625..C63F ; LVT # Lo [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH C641..C65B ; LVT # Lo [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH C65D..C677 ; LVT # Lo [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH C679..C693 ; LVT # Lo [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH C695..C6AF ; LVT # Lo [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH C6B1..C6CB ; LVT # Lo [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH C6CD..C6E7 ; LVT # Lo [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH C6E9..C703 ; LVT # Lo [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH C705..C71F ; LVT # Lo [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH C721..C73B ; LVT # Lo [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH C73D..C757 ; LVT # Lo [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH C759..C773 ; LVT # Lo [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH C775..C78F ; LVT # Lo [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH C791..C7AB ; LVT # Lo [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH C7AD..C7C7 ; LVT # Lo [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH C7C9..C7E3 ; LVT # Lo [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH C7E5..C7FF ; LVT # Lo [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH C801..C81B ; LVT # Lo [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH C81D..C837 ; LVT # Lo [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH C839..C853 ; LVT # Lo [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH C855..C86F ; LVT # Lo [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH C871..C88B ; LVT # Lo [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH C88D..C8A7 ; LVT # Lo [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH C8A9..C8C3 ; LVT # Lo [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH C8C5..C8DF ; LVT # Lo [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH C8E1..C8FB ; LVT # Lo [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH C8FD..C917 ; LVT # Lo [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH C919..C933 ; LVT # Lo [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH C935..C94F ; LVT # Lo [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH C951..C96B ; LVT # Lo [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH C96D..C987 ; LVT # Lo [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH C989..C9A3 ; LVT # Lo [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH C9A5..C9BF ; LVT # Lo [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH C9C1..C9DB ; LVT # Lo [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH C9DD..C9F7 ; LVT # Lo [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH C9F9..CA13 ; LVT # Lo [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH CA15..CA2F ; LVT # Lo [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH CA31..CA4B ; LVT # Lo [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH CA4D..CA67 ; LVT # Lo [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH CA69..CA83 ; LVT # Lo [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH CA85..CA9F ; LVT # Lo [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH CAA1..CABB ; LVT # Lo [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH CABD..CAD7 ; LVT # Lo [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH CAD9..CAF3 ; LVT # Lo [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH CAF5..CB0F ; LVT # Lo [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH CB11..CB2B ; LVT # Lo [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH CB2D..CB47 ; LVT # Lo [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH CB49..CB63 ; LVT # Lo [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH CB65..CB7F ; LVT # Lo [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH CB81..CB9B ; LVT # Lo [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH CB9D..CBB7 ; LVT # Lo [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH CBB9..CBD3 ; LVT # Lo [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH CBD5..CBEF ; LVT # Lo [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH CBF1..CC0B ; LVT # Lo [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH CC0D..CC27 ; LVT # Lo [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH CC29..CC43 ; LVT # Lo [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH CC45..CC5F ; LVT # Lo [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH CC61..CC7B ; LVT # Lo [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH CC7D..CC97 ; LVT # Lo [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH CC99..CCB3 ; LVT # Lo [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH CCB5..CCCF ; LVT # Lo [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH CCD1..CCEB ; LVT # Lo [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH CCED..CD07 ; LVT # Lo [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH CD09..CD23 ; LVT # Lo [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH CD25..CD3F ; LVT # Lo [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH CD41..CD5B ; LVT # Lo [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH CD5D..CD77 ; LVT # Lo [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH CD79..CD93 ; LVT # Lo [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH CD95..CDAF ; LVT # Lo [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH CDB1..CDCB ; LVT # Lo [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH CDCD..CDE7 ; LVT # Lo [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH CDE9..CE03 ; LVT # Lo [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH CE05..CE1F ; LVT # Lo [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH CE21..CE3B ; LVT # Lo [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH CE3D..CE57 ; LVT # Lo [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH CE59..CE73 ; LVT # Lo [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH CE75..CE8F ; LVT # Lo [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH CE91..CEAB ; LVT # Lo [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH CEAD..CEC7 ; LVT # Lo [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH CEC9..CEE3 ; LVT # Lo [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH CEE5..CEFF ; LVT # Lo [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH CF01..CF1B ; LVT # Lo [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH CF1D..CF37 ; LVT # Lo [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH CF39..CF53 ; LVT # Lo [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH CF55..CF6F ; LVT # Lo [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH CF71..CF8B ; LVT # Lo [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH CF8D..CFA7 ; LVT # Lo [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH CFA9..CFC3 ; LVT # Lo [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH CFC5..CFDF ; LVT # Lo [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH CFE1..CFFB ; LVT # Lo [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH CFFD..D017 ; LVT # Lo [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH D019..D033 ; LVT # Lo [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH D035..D04F ; LVT # Lo [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH D051..D06B ; LVT # Lo [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH D06D..D087 ; LVT # Lo [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH D089..D0A3 ; LVT # Lo [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH D0A5..D0BF ; LVT # Lo [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH D0C1..D0DB ; LVT # Lo [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH D0DD..D0F7 ; LVT # Lo [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH D0F9..D113 ; LVT # Lo [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH D115..D12F ; LVT # Lo [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH D131..D14B ; LVT # Lo [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH D14D..D167 ; LVT # Lo [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH D169..D183 ; LVT # Lo [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH D185..D19F ; LVT # Lo [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH D1A1..D1BB ; LVT # Lo [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH D1BD..D1D7 ; LVT # Lo [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH D1D9..D1F3 ; LVT # Lo [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH D1F5..D20F ; LVT # Lo [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH D211..D22B ; LVT # Lo [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH D22D..D247 ; LVT # Lo [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH D249..D263 ; LVT # Lo [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH D265..D27F ; LVT # Lo [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH D281..D29B ; LVT # Lo [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH D29D..D2B7 ; LVT # Lo [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH D2B9..D2D3 ; LVT # Lo [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH D2D5..D2EF ; LVT # Lo [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH D2F1..D30B ; LVT # Lo [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH D30D..D327 ; LVT # Lo [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH D329..D343 ; LVT # Lo [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH D345..D35F ; LVT # Lo [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH D361..D37B ; LVT # Lo [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH D37D..D397 ; LVT # Lo [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH D399..D3B3 ; LVT # Lo [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH D3B5..D3CF ; LVT # Lo [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH D3D1..D3EB ; LVT # Lo [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH D3ED..D407 ; LVT # Lo [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH D409..D423 ; LVT # Lo [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH D425..D43F ; LVT # Lo [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH D441..D45B ; LVT # Lo [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH D45D..D477 ; LVT # Lo [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH D479..D493 ; LVT # Lo [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH D495..D4AF ; LVT # Lo [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH D4B1..D4CB ; LVT # Lo [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH D4CD..D4E7 ; LVT # Lo [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH D4E9..D503 ; LVT # Lo [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH D505..D51F ; LVT # Lo [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH D521..D53B ; LVT # Lo [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH D53D..D557 ; LVT # Lo [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH D559..D573 ; LVT # Lo [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH D575..D58F ; LVT # Lo [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH D591..D5AB ; LVT # Lo [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH D5AD..D5C7 ; LVT # Lo [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH D5C9..D5E3 ; LVT # Lo [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH D5E5..D5FF ; LVT # Lo [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH D601..D61B ; LVT # Lo [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH D61D..D637 ; LVT # Lo [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH D639..D653 ; LVT # Lo [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH D655..D66F ; LVT # Lo [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH D671..D68B ; LVT # Lo [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH D68D..D6A7 ; LVT # Lo [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH D6A9..D6C3 ; LVT # Lo [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH D6C5..D6DF ; LVT # Lo [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH D6E1..D6FB ; LVT # Lo [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH D6FD..D717 ; LVT # Lo [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH D719..D733 ; LVT # Lo [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH D735..D74F ; LVT # Lo [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH D751..D76B ; LVT # Lo [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH D76D..D787 ; LVT # Lo [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH elixir-lang-1.1.0~0.20150708/lib/elixir/unicode/SpecialCasing.txt000066400000000000000000000213701254730255300240560ustar00rootroot0000000000000000DF; 00DF; 0053 0073; 0053 0053; # LATIN SMALL LETTER SHARP S 0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE FB00; FB00; 0046 0066; 0046 0046; # LATIN SMALL LIGATURE FF FB01; FB01; 0046 0069; 0046 0049; # LATIN SMALL LIGATURE FI FB02; FB02; 0046 006C; 0046 004C; # LATIN SMALL LIGATURE FL FB03; FB03; 0046 0066 0069; 0046 0046 0049; # LATIN SMALL LIGATURE FFI FB04; FB04; 0046 0066 006C; 0046 0046 004C; # LATIN SMALL LIGATURE FFL FB05; FB05; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE LONG S T FB06; FB06; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE ST 0587; 0587; 0535 0582; 0535 0552; # ARMENIAN SMALL LIGATURE ECH YIWN FB13; FB13; 0544 0576; 0544 0546; # ARMENIAN SMALL LIGATURE MEN NOW FB14; FB14; 0544 0565; 0544 0535; # ARMENIAN SMALL LIGATURE MEN ECH FB15; FB15; 0544 056B; 0544 053B; # ARMENIAN SMALL LIGATURE MEN INI FB16; FB16; 054E 0576; 054E 0546; # ARMENIAN SMALL LIGATURE VEW NOW FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH 0149; 0149; 02BC 004E; 02BC 004E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE 0390; 0390; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS 03B0; 03B0; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS 01F0; 01F0; 004A 030C; 004A 030C; # LATIN SMALL LETTER J WITH CARON 1E96; 1E96; 0048 0331; 0048 0331; # LATIN SMALL LETTER H WITH LINE BELOW 1E97; 1E97; 0054 0308; 0054 0308; # LATIN SMALL LETTER T WITH DIAERESIS 1E98; 1E98; 0057 030A; 0057 030A; # LATIN SMALL LETTER W WITH RING ABOVE 1E99; 1E99; 0059 030A; 0059 030A; # LATIN SMALL LETTER Y WITH RING ABOVE 1E9A; 1E9A; 0041 02BE; 0041 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING 1F50; 1F50; 03A5 0313; 03A5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI 1F52; 1F52; 03A5 0313 0300; 03A5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA 1F54; 1F54; 03A5 0313 0301; 03A5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA 1F56; 1F56; 03A5 0313 0342; 03A5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI 1FB6; 1FB6; 0391 0342; 0391 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI 1FC6; 1FC6; 0397 0342; 0397 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI 1FD2; 1FD2; 0399 0308 0300; 0399 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA 1FD3; 1FD3; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA 1FD6; 1FD6; 0399 0342; 0399 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI 1FD7; 1FD7; 0399 0308 0342; 0399 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI 1FE2; 1FE2; 03A5 0308 0300; 03A5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA 1FE3; 1FE3; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA 1FE4; 1FE4; 03A1 0313; 03A1 0313; # GREEK SMALL LETTER RHO WITH PSILI 1FE6; 1FE6; 03A5 0342; 03A5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI 1FE7; 1FE7; 03A5 0308 0342; 03A5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI 1FF6; 1FF6; 03A9 0342; 03A9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI 1F80; 1F80; 1F88; 1F08 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI 1F81; 1F81; 1F89; 1F09 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI 1F82; 1F82; 1F8A; 1F0A 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1F83; 1F83; 1F8B; 1F0B 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1F84; 1F84; 1F8C; 1F0C 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1F85; 1F85; 1F8D; 1F0D 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1F86; 1F86; 1F8E; 1F0E 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1F87; 1F87; 1F8F; 1F0F 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1F88; 1F80; 1F88; 1F08 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI 1F89; 1F81; 1F89; 1F09 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI 1F8A; 1F82; 1F8A; 1F0A 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F8B; 1F83; 1F8B; 1F0B 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F8C; 1F84; 1F8C; 1F0C 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F8D; 1F85; 1F8D; 1F0D 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F8E; 1F86; 1F8E; 1F0E 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F8F; 1F87; 1F8F; 1F0F 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1F90; 1F90; 1F98; 1F28 0399; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI 1F91; 1F91; 1F99; 1F29 0399; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI 1F92; 1F92; 1F9A; 1F2A 0399; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1F93; 1F93; 1F9B; 1F2B 0399; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1F94; 1F94; 1F9C; 1F2C 0399; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1F95; 1F95; 1F9D; 1F2D 0399; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1F96; 1F96; 1F9E; 1F2E 0399; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1F97; 1F97; 1F9F; 1F2F 0399; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1F98; 1F90; 1F98; 1F28 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI 1F99; 1F91; 1F99; 1F29 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI 1F9A; 1F92; 1F9A; 1F2A 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F9B; 1F93; 1F9B; 1F2B 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F9C; 1F94; 1F9C; 1F2C 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F9D; 1F95; 1F9D; 1F2D 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F9E; 1F96; 1F9E; 1F2E 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F9F; 1F97; 1F9F; 1F2F 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1FA0; 1FA0; 1FA8; 1F68 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI 1FA1; 1FA1; 1FA9; 1F69 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI 1FA2; 1FA2; 1FAA; 1F6A 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1FA3; 1FA3; 1FAB; 1F6B 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1FA4; 1FA4; 1FAC; 1F6C 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1FA5; 1FA5; 1FAD; 1F6D 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1FA6; 1FA6; 1FAE; 1F6E 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1FA7; 1FA7; 1FAF; 1F6F 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1FA8; 1FA0; 1FA8; 1F68 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI 1FA9; 1FA1; 1FA9; 1F69 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI 1FAA; 1FA2; 1FAA; 1F6A 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1FAB; 1FA3; 1FAB; 1F6B 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1FAC; 1FA4; 1FAC; 1F6C 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1FAD; 1FA5; 1FAD; 1F6D 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1FAE; 1FA6; 1FAE; 1F6E 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1FAF; 1FA7; 1FAF; 1F6F 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1FB3; 1FB3; 1FBC; 0391 0399; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI 1FBC; 1FB3; 1FBC; 0391 0399; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI 1FC3; 1FC3; 1FCC; 0397 0399; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI 1FCC; 1FC3; 1FCC; 0397 0399; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI 1FF3; 1FF3; 1FFC; 03A9 0399; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI 1FFC; 1FF3; 1FFC; 03A9 0399; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI 1FB2; 1FB2; 1FBA 0345; 1FBA 0399; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI 1FB4; 1FB4; 0386 0345; 0386 0399; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI 1FC2; 1FC2; 1FCA 0345; 1FCA 0399; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI 1FC4; 1FC4; 0389 0345; 0389 0399; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI 1FF2; 1FF2; 1FFA 0345; 1FFA 0399; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI 1FF4; 1FF4; 038F 0345; 038F 0399; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI 1FB7; 1FB7; 0391 0342 0345; 0391 0342 0399; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI 1FC7; 1FC7; 0397 0342 0345; 0397 0342 0399; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI 1FF7; 1FF7; 03A9 0342 0345; 03A9 0342 0399; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI elixir-lang-1.1.0~0.20150708/lib/elixir/unicode/UnicodeData.txt000066400000000000000000056043021254730255300235400ustar00rootroot000000000000000000;;Cc;0;BN;;;;;N;NULL;;;; 0001;;Cc;0;BN;;;;;N;START OF HEADING;;;; 0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; 0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; 0004;;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; 0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; 0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;;Cc;0;BN;;;;;N;BELL;;;; 0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; 0009;;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; 000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; 000B;;Cc;0;S;;;;;N;LINE TABULATION;;;; 000C;;Cc;0;WS;;;;;N;FORM FEED (FF);;;; 000D;;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; 000E;;Cc;0;BN;;;;;N;SHIFT OUT;;;; 000F;;Cc;0;BN;;;;;N;SHIFT IN;;;; 0010;;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; 0011;;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; 0012;;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; 0013;;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; 0014;;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; 0015;;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; 0016;;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; 0017;;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; 0018;;Cc;0;BN;;;;;N;CANCEL;;;; 0019;;Cc;0;BN;;;;;N;END OF MEDIUM;;;; 001A;;Cc;0;BN;;;;;N;SUBSTITUTE;;;; 001B;;Cc;0;BN;;;;;N;ESCAPE;;;; 001C;;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; 001D;;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; 001E;;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; 001F;;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; 0020;SPACE;Zs;0;WS;;;;;N;;;;; 0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; 0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; 0026;AMPERSAND;Po;0;ON;;;;;N;;;;; 0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; 0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; 0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; 002A;ASTERISK;Po;0;ON;;;;;N;;;;; 002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;; 002C;COMMA;Po;0;CS;;;;;N;;;;; 002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;; 002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; 002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;; 0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; 0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; 0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; 0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; 0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; 0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; 0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; 0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; 0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; 0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; 003A;COLON;Po;0;CS;;;;;N;;;;; 003B;SEMICOLON;Po;0;ON;;;;;N;;;;; 003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; 0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; 0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; 0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; 0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; 0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; 0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; 0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; 0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; 0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; 0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; 004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; 004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; 004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; 004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; 004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; 004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; 0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; 0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; 0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; 0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; 0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; 0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; 0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; 0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; 0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; 0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; 005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; 005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; 005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; 005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; 005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; 005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; 0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; 0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A 006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B 006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C 006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D 006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E 006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F 0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A 007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; 007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; 007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; 007E;TILDE;Sm;0;ON;;;;;N;;;;; 007F;;Cc;0;BN;;;;;N;DELETE;;;; 0080;;Cc;0;BN;;;;;N;;;;; 0081;;Cc;0;BN;;;;;N;;;;; 0082;;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; 0083;;Cc;0;BN;;;;;N;NO BREAK HERE;;;; 0084;;Cc;0;BN;;;;;N;;;;; 0085;;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; 0086;;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; 0087;;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; 0088;;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; 0089;;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; 008A;;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; 008B;;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; 008C;;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; 008D;;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; 008E;;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; 008F;;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; 0090;;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; 0091;;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; 0092;;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; 0093;;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; 0094;;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; 0095;;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; 0096;;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; 0097;;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; 0098;;Cc;0;BN;;;;;N;START OF STRING;;;; 0099;;Cc;0;BN;;;;;N;;;;; 009A;;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; 009B;;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; 009C;;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; 009D;;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; 009E;;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; 009F;;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; 00A0;NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;NON-BREAKING SPACE;;;; 00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; 00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; 00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; 00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; 00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;; 00A8;DIAERESIS;Sk;0;ON; 0020 0308;;;;N;SPACING DIAERESIS;;;; 00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; 00AA;FEMININE ORDINAL INDICATOR;Lo;0;L; 0061;;;;N;;;;; 00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;; 00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; 00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;; 00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; 00AF;MACRON;Sk;0;ON; 0020 0304;;;;N;SPACING MACRON;;;; 00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; 00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; 00B2;SUPERSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;; 00B3;SUPERSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;; 00B4;ACUTE ACCENT;Sk;0;ON; 0020 0301;;;;N;SPACING ACUTE;;;; 00B5;MICRO SIGN;Ll;0;L; 03BC;;;;N;;;039C;;039C 00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;; 00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; 00B8;CEDILLA;Sk;0;ON; 0020 0327;;;;N;SPACING CEDILLA;;;; 00B9;SUPERSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; 00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L; 006F;;;;N;;;;; 00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; 00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; 00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; 00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; 00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; 00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; 00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; 00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; 00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; 00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; 00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6; 00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; 00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; 00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; 00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; 00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; 00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; 00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; 00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; 00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; 00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0; 00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; 00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; 00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; 00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; 00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; 00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; 00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; 00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; 00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; 00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; 00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; 00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; 00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE; 00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;; 00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6 00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA 00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB 00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC 00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD 00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE 00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF 00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0 00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA 00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB 00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC 00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD 00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE 00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; 0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; 0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; 0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; 0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; 0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; 010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A 010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; 010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C 010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; 010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E 0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; 0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; 0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; 0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; 0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; 0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; 011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A 011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; 011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C 011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; 011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E 0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; 0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; 0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; 0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; 0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; 0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; 012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A 012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; 012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C 012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; 012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E 0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L; 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; 0133;LATIN SMALL LIGATURE IJ;Ll;0;L; 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; 0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; 0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;; 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; 013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; 013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B 013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; 013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L; 004C 00B7;;;;N;;;;0140; 0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L; 006C 00B7;;;;N;;;013F;;013F 0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; 0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; 0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; 0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L; 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; 014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B; 014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A 014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; 014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C 014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; 014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E 0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; 0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; 0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; 0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; 0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; 0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; 015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A 015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; 015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C 015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F; 015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E 0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; 0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163; 0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162 0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; 0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; 0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; 0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; 016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A 016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; 016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C 016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; 016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E 0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; 0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; 0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; 0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; 0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; 0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; 017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; 017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B 017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; 017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D 017F;LATIN SMALL LETTER LONG S;Ll;0;L; 0073;;;;N;;;0053;;0053 0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243 0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; 0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; 0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; 0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; 0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; 0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256; 018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; 018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; 018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B 018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; 018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; 018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; 0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; 0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; 0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; 0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; 0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6 0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; 0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; 0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; 0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D 019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;; 019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; 019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; 019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275; 01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; 01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3; 01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2 01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; 01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280; 01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; 01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; 01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; 01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; 01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; 01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC 01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; 01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; 01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF 01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; 01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; 01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; 01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; 01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; 01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; 01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; 01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; 01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; 01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC 01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; 01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; 01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; 01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; 01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; 01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L; 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L; 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5 01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L; 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 01C7;LATIN CAPITAL LETTER LJ;Lu;0;L; 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L; 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8 01C9;LATIN SMALL LETTER LJ;Ll;0;L; 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 01CA;LATIN CAPITAL LETTER NJ;Lu;0;L; 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB 01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L; 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB 01CC;LATIN SMALL LETTER NJ;Ll;0;L; 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB 01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; 01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD 01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; 01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF 01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; 01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; 01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; 01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; 01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; 01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; 01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB 01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E 01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; 01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE 01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; 01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3; 01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2 01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; 01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; 01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; 01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; 01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA 01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; 01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC 01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; 01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE 01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; 01F1;LATIN CAPITAL LETTER DZ;Lu;0;L; 0044 005A;;;;N;;;;01F3;01F2 01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L; 0044 007A;;;;N;;;01F1;01F3;01F2 01F3;LATIN SMALL LETTER DZ;Ll;0;L; 0064 007A;;;;N;;;01F1;;01F2 01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; 01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; 01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; 01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; 01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; 01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA 01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD; 01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC 01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; 01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE 0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; 0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; 0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; 0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; 0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; 0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; 020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A 020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; 020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C 020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; 020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E 0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; 0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; 0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; 0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; 0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219; 0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218 021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B; 021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A 021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; 021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C 021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; 021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E 0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; 0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;; 0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; 0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; 0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; 0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; 0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; 022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A 022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; 022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C 022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; 022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E 0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; 0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; 0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;; 0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;; 0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;; 0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;; 0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;; 0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;; 023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65; 023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C; 023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B 023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A; 023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66; 023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E 0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F 0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242; 0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241 0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180; 0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289; 0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C; 0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247; 0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246 0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249; 0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248 024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B; 024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A 024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D; 024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C 024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F; 024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E 0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F 0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D 0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70 0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; 0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A 0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; 0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F 025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; 025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;A7AB;;A7AB 025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; 025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; 025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; 0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;A7AC;;A7AC 0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; 0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; 0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D 0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;A7AA;;A7AA 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;; 026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;A7AD;;A7AD 026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; 026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; 026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C 0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; 0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E 0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D 0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; 0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; 0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F 0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; 0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; 0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; 0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; 027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; 027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64 027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; 027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; 0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6 0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; 0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;; 0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; 0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; 0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; 0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;A7B1;;A7B1 0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE 0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244 028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245 028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; 028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; 028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; 0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; 0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; 0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; 0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; 0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; 0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; 0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; 0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; 029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; 029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; 029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; 029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;; 029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;A7B0;;A7B0 029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; 02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; 02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; 02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; 02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; 02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; 02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; 02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; 02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; 02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; 02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; 02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; 02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; 02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;; 02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;; 02B0;MODIFIER LETTER SMALL H;Lm;0;L; 0068;;;;N;;;;; 02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L; 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; 02B2;MODIFIER LETTER SMALL J;Lm;0;L; 006A;;;;N;;;;; 02B3;MODIFIER LETTER SMALL R;Lm;0;L; 0072;;;;N;;;;; 02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L; 0279;;;;N;;;;; 02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L; 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; 02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L; 0281;;;;N;;;;; 02B7;MODIFIER LETTER SMALL W;Lm;0;L; 0077;;;;N;;;;; 02B8;MODIFIER LETTER SMALL Y;Lm;0;L; 0079;;;;N;;;;; 02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;; 02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;; 02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; 02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; 02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; 02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; 02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; 02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;; 02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;; 02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;; 02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;; 02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;; 02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; 02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; 02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; 02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; 02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; 02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; 02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; 02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; 02D8;BREVE;Sk;0;ON; 0020 0306;;;;N;SPACING BREVE;;;; 02D9;DOT ABOVE;Sk;0;ON; 0020 0307;;;;N;SPACING DOT ABOVE;;;; 02DA;RING ABOVE;Sk;0;ON; 0020 030A;;;;N;SPACING RING ABOVE;;;; 02DB;OGONEK;Sk;0;ON; 0020 0328;;;;N;SPACING OGONEK;;;; 02DC;SMALL TILDE;Sk;0;ON; 0020 0303;;;;N;SPACING TILDE;;;; 02DD;DOUBLE ACUTE ACCENT;Sk;0;ON; 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; 02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; 02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; 02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L; 0263;;;;N;;;;; 02E1;MODIFIER LETTER SMALL L;Lm;0;L; 006C;;;;N;;;;; 02E2;MODIFIER LETTER SMALL S;Lm;0;L; 0073;;;;N;;;;; 02E3;MODIFIER LETTER SMALL X;Lm;0;L; 0078;;;;N;;;;; 02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L; 0295;;;;N;;;;; 02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; 02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;; 02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; 02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; 02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;; 02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;; 02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;; 02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;; 02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;; 02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;; 02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;; 02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;; 02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;; 0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; 0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;; 0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; 0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; 0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; 0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; 0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;; 0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; 0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;; 0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; 030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; 030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; 030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; 030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; 030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; 030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; 0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; 0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; 0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; 0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;; 0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;; 0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; 0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; 0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; 0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; 0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; 031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; 031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; 031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; 031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; 031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; 031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; 0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; 0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; 0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; 0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; 0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; 0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; 0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; 0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; 0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; 0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; 032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; 032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; 032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; 032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; 032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; 032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; 0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; 0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; 0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; 0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; 0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; 0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; 0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; 0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; 0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; 0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; 033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; 033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; 033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; 033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; 033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; 033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; 0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;; 0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;; 0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; 0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; 0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; 0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; 0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; 034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; 034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; 034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; 034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; 0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;; 0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;; 0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; 0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;; 035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;; 035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;; 035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;; 035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;; 0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; 0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; 0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; 0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; 0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; 0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; 0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; 0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; 0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; 0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; 036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; 036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; 036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; 036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; 036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; 036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; 0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371; 0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370 0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373; 0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372 0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;; 0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;; 0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377; 0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376 037A;GREEK YPOGEGRAMMENI;Lm;0;L; 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; 037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD 037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE 037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF 037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;; 037F;GREEK CAPITAL LETTER YOT;Lu;0;L;;;;;N;;;;03F3; 0384;GREEK TONOS;Sk;0;ON; 0020 0301;;;;N;GREEK SPACING TONOS;;;; 0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; 0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; 0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; 0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; 0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; 038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; 038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; 038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; 038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; 0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; 0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; 0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; 0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; 0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; 0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; 0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; 0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; 0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; 039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; 039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; 039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; 039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; 039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; 039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; 03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; 03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; 03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; 03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; 03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; 03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; 03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; 03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; 03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; 03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; 03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; 03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A 03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; 03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A 03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B 03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C 03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D 03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E 03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F 03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA 03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB 03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C 03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E 03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F 03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7; 03D0;GREEK BETA SYMBOL;Ll;0;L; 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 03D1;GREEK THETA SYMBOL;Ll;0;L; 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L; 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; 03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; 03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; 03D5;GREEK PHI SYMBOL;Ll;0;L; 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 03D6;GREEK PI SYMBOL;Ll;0;L; 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF 03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9; 03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8 03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; 03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA 03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; 03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC 03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; 03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE 03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; 03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; 03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; 03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; 03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; 03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; 03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA 03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; 03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC 03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; 03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE 03F0;GREEK KAPPA SYMBOL;Ll;0;L; 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A 03F1;GREEK RHO SYMBOL;Ll;0;L; 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L; 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9 03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;037F;;037F 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L; 0398;;;;N;;;;03B8; 03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L; 03B5;;;;N;;;0395;;0395 03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; 03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8; 03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7 03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L; 03A3;;;;N;;;;03F2; 03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB; 03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA 03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;; 03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B; 03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C; 03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D; 0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; 0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; 0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452; 0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; 0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; 0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; 0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; 0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457; 0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; 0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; 040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; 040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B; 040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; 040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; 040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E; 040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; 0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; 0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; 0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; 0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; 0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; 0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; 0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; 0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; 0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; 0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; 041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; 041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; 041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; 041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; 041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; 041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; 0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; 0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; 0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; 0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; 0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; 0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; 0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; 0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; 0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; 0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; 042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; 042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; 042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; 042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; 042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; 042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; 0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A 043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B 043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C 043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D 043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E 043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F 0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A 044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B 044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C 044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D 044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E 044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F 0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402 0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407 0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A 045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B 045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C 045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D 045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E 045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F 0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; 0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; 0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; 0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; 0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; 0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; 046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A 046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; 046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C 046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; 046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E 0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; 0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; 0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; 0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; 0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; 0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; 047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A 047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; 047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C 047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; 047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E 0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; 0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; 0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; 0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; 0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; 0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; 0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;; 0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; 0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; 048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A 048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; 048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C 048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; 048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E 0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; 0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; 0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; 0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; 0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; 0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; 049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A 049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; 049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C 049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; 049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E 04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; 04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; 04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; 04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7; 04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6 04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; 04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; 04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA 04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; 04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC 04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; 04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE 04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; 04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; 04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5; 04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4 04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; 04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; 04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; 04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA 04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; 04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC 04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; 04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE 04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF; 04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; 04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; 04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; 04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; 04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; 04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; 04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB 04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; 04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD 04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0 04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; 04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; 04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; 04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; 04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; 04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; 04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA 04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; 04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC 04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; 04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE 04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; 04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; 04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; 04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; 04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; 04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; 04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA 04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; 04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC 04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; 04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE 04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; 04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; 04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; 04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7; 04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6 04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; 04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB; 04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA 04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD; 04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC 04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF; 04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE 0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; 0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; 0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; 0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; 0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; 0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; 050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A 050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; 050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C 050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; 050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E 0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511; 0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510 0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513; 0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512 0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515; 0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514 0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517; 0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516 0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519; 0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518 051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B; 051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A 051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D; 051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C 051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F; 051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E 0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521; 0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520 0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523; 0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; 0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527; 0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526 0528;CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK;Lu;0;L;;;;;N;;;;0529; 0529;CYRILLIC SMALL LETTER EN WITH LEFT HOOK;Ll;0;L;;;;;N;;;0528;;0528 052A;CYRILLIC CAPITAL LETTER DZZHE;Lu;0;L;;;;;N;;;;052B; 052B;CYRILLIC SMALL LETTER DZZHE;Ll;0;L;;;;;N;;;052A;;052A 052C;CYRILLIC CAPITAL LETTER DCHE;Lu;0;L;;;;;N;;;;052D; 052D;CYRILLIC SMALL LETTER DCHE;Ll;0;L;;;;;N;;;052C;;052C 052E;CYRILLIC CAPITAL LETTER EL WITH DESCENDER;Lu;0;L;;;;;N;;;;052F; 052F;CYRILLIC SMALL LETTER EL WITH DESCENDER;Ll;0;L;;;;;N;;;052E;;052E 0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; 0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; 0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; 0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; 0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; 0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; 0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; 0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; 0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; 053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; 053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; 053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; 053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; 053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; 053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; 0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; 0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; 0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; 0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; 0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; 0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; 0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; 0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; 0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; 0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; 054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; 054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; 054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; 054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; 054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; 054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; 0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; 0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; 0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; 0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; 0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; 0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; 0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; 0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; 055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; 055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; 055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; 055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; 055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; 0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A 056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B 056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C 056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D 056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E 056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F 0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A 057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B 057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C 057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D 057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E 057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F 0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L; 0565 0582;;;;N;;;;; 0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; 058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; 058D;RIGHT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; 058E;LEFT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; 058F;ARMENIAN DRAM SIGN;Sc;0;ET;;;;;N;;;;; 0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; 0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; 0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; 0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; 0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; 0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;; 0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; 0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;; 0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; 059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; 059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; 059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; 059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; 059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; 059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; 05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; 05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; 05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;; 05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; 05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; 05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;; 05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; 05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; 05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;; 05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; 05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;; 05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; 05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; 05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; 05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; 05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; 05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; 05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; 05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; 05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; 05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; 05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; 05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; 05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; 05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; 05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; 05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;; 05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; 05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;; 05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;; 05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;; 05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; 05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;; 05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; 05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; 05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;; 05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; 05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;; 05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;; 05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;; 05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; 05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; 05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; 05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; 05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; 05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; 05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; 05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; 05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; 05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; 05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; 05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; 05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; 05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; 05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; 05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; 05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; 05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; 05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; 05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; 05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; 05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; 05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; 05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; 05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; 05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; 05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; 05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; 0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;; 0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;; 0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;; 0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;; 0604;ARABIC SIGN SAMVAT;Cf;0;AN;;;;;N;;;;; 0605;ARABIC NUMBER MARK ABOVE;Cf;0;AN;;;;;N;;;;; 0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;; 0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;; 0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;; 0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;; 060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; 060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;; 060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;; 060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;; 0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;; 0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;; 0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;; 0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;; 0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;; 0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;; 0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;; 0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;; 0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;; 0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;; 061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;; 061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; 0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; 0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; 0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; 0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; 0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; 0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; 0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; 0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; 0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; 0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; 062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; 062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; 062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; 062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; 062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; 062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; 0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; 0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; 0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; 0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; 0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; 0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; 0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; 0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; 0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; 063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; 063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; 0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; 0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; 0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; 0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; 0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; 0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; 0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; 0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; 064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; 064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; 064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; 064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; 064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; 064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; 0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; 0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; 0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; 0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; 0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; 0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;; 0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;; 0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; 0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;; 065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; 065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; 065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; 0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; 0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; 0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; 0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; 0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; 0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; 0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; 0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; 0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; 066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; 066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; 066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; 066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; 066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; 066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; 0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; 0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; 0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; 0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; 0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; 0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL; 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; 0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL; 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; 0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL; 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; 0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL; 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; 0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; 067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; 067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; 067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; 067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; 067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; 067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; 0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; 0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; 0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; 0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; 0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; 0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; 0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; 0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; 0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; 0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; 068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; 068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; 068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; 068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; 0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; 0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; 0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; 0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; 0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; 0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; 0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; 0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; 0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; 069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; 06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; 06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; 06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; 06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; 06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; 06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; 06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; 06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; 06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; 06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; 06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; 06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;; 06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; 06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; 06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; 06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; 06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; 06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; 06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; 06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; 06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; 06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; 06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; 06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; 06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; 06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; 06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; 06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; 06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; 06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; 06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; 06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; 06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; 06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; 06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;; 06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; 06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; 06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; 06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; 06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; 06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; 06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; 06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; 06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; 06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; 06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; 06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;; 06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; 06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; 06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; 06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; 06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; 06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; 06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; 06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; 06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; 06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; 06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; 06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; 06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; 06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; 06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; 06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; 06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; 06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; 06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; 06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; 06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; 06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; 06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; 06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; 06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; 06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; 06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; 06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; 0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; 0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; 0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; 0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; 070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; 070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; 070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; 070F;SYRIAC ABBREVIATION MARK;Cf;0;AL;;;;;N;;;;; 0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; 0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; 0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; 0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; 0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; 0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; 0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; 0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; 0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; 071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; 071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; 071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; 071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; 071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; 0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; 0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; 0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; 0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; 0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; 0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; 0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; 0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; 0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; 0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; 072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; 072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; 072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; 072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;; 072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;; 072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;; 0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; 0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; 0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; 0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; 0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; 073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; 073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; 073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; 073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; 0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; 0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; 0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; 0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; 0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; 074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; 074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;; 074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;; 074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;; 0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;; 0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; 0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;; 075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;; 075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;; 0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;; 076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;; 076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;; 076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; 0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;; 077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; 0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; 0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; 0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; 0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; 0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; 0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; 0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; 0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; 0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; 078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; 078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; 078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; 078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; 078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; 078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; 0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; 0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; 0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; 0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; 0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; 0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; 0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; 0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; 0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; 0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; 079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; 079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; 079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; 079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; 079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; 079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; 07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; 07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; 07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; 07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; 07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; 07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; 07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; 07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; 07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; 07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; 07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; 07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; 07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; 07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; 07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; 07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; 07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; 07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; 07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; 07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; 07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; 07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; 07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; 07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; 07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; 07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; 07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; 07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; 07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;; 07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;; 07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;; 07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;; 07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;; 07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;; 07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;; 07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;; 07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;; 07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;; 07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;; 07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;; 07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;; 07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;; 07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;; 07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;; 07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;; 07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;; 07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;; 07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;; 07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;; 07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;; 07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;; 07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;; 07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;; 07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;; 07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;; 07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;; 07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;; 07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;; 07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;; 07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;; 07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;; 07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;; 07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;; 07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;; 07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;; 07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;; 07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;; 07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;; 07F8;NKO COMMA;Po;0;ON;;;;;N;;;;; 07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;; 0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;; 0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;; 0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;; 0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;; 0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;; 0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;; 0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;; 0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;; 0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;; 0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;; 080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;; 080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;; 080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;; 080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;; 080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;; 080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;; 0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;; 0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;; 0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;; 0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;; 0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;; 0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;; 0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;; 0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;; 0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;; 0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;; 081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;; 081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;; 081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;; 081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; 081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;; 081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;; 0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;; 0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;; 0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;; 0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;; 0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;; 0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;; 0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;; 0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;; 0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;; 0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;; 082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;; 082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;; 082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;; 0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;; 0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;; 0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;; 0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;; 0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;; 0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;; 0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;; 0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;; 0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;; 0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;; 083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;; 083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;; 083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; 083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; 083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; 0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;; 0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;; 0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;; 0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;; 0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;; 0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;; 0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;; 0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;; 0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;; 0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;; 084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;; 084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;; 084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;; 084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;; 084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;; 084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;; 0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;; 0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;; 0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;; 0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;; 0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;; 0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;; 0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;; 0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;; 0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;; 0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;; 085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; 085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A3;ARABIC LETTER TAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A4;ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A5;ARABIC LETTER QAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 08A6;ARABIC LETTER LAM WITH DOUBLE BAR;Lo;0;AL;;;;;N;;;;; 08A7;ARABIC LETTER MEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A8;ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A9;ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 08AA;ARABIC LETTER REH WITH LOOP;Lo;0;AL;;;;;N;;;;; 08AB;ARABIC LETTER WAW WITH DOT WITHIN;Lo;0;AL;;;;;N;;;;; 08AC;ARABIC LETTER ROHINGYA YEH;Lo;0;AL;;;;;N;;;;; 08AD;ARABIC LETTER LOW ALEF;Lo;0;AL;;;;;N;;;;; 08AE;ARABIC LETTER DAL WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08AF;ARABIC LETTER SAD WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08B0;ARABIC LETTER GAF WITH INVERTED STROKE;Lo;0;AL;;;;;N;;;;; 08B1;ARABIC LETTER STRAIGHT WAW;Lo;0;AL;;;;;N;;;;; 08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; 08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;; 08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;; 08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;; 08E7;ARABIC CURLY FATHATAN;Mn;230;NSM;;;;;N;;;;; 08E8;ARABIC CURLY DAMMATAN;Mn;230;NSM;;;;;N;;;;; 08E9;ARABIC CURLY KASRATAN;Mn;220;NSM;;;;;N;;;;; 08EA;ARABIC TONE ONE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 08EB;ARABIC TONE TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 08EC;ARABIC TONE LOOP ABOVE;Mn;230;NSM;;;;;N;;;;; 08ED;ARABIC TONE ONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; 08EE;ARABIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 08EF;ARABIC TONE LOOP BELOW;Mn;220;NSM;;;;;N;;;;; 08F0;ARABIC OPEN FATHATAN;Mn;27;NSM;;;;;N;;;;; 08F1;ARABIC OPEN DAMMATAN;Mn;28;NSM;;;;;N;;;;; 08F2;ARABIC OPEN KASRATAN;Mn;29;NSM;;;;;N;;;;; 08F3;ARABIC SMALL HIGH WAW;Mn;230;NSM;;;;;N;;;;; 08F4;ARABIC FATHA WITH RING;Mn;230;NSM;;;;;N;;;;; 08F5;ARABIC FATHA WITH DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 08F6;ARABIC KASRA WITH DOT BELOW;Mn;220;NSM;;;;;N;;;;; 08F7;ARABIC LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08F8;ARABIC RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08F9;ARABIC LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 08FA;ARABIC RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 08FB;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08FC;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FD;ARABIC RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FE;ARABIC DAMMA WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FF;ARABIC MARK SIDEWAYS NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; 0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;; 0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; 0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; 0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; 0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; 0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; 090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; 090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; 090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; 090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; 0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; 0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; 0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; 0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; 0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; 0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; 0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; 0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; 0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; 0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; 091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; 091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; 091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; 091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; 091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; 091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; 0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; 0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; 0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; 0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; 0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; 0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; 0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; 0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; 092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; 092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; 092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; 092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; 092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; 092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; 0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; 0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; 0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; 0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; 0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; 0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; 0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; 0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; 0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; 0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; 093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; 093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; 093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; 094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;; 0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; 0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; 0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; 0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; 0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; 0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; 0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; 095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; 095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; 095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; 095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; 095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; 095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; 0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; 0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; 0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; 0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;; 0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;; 0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;; 0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;; 0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;; 0978;DEVANAGARI LETTER MARWARI DDA;Lo;0;L;;;;;N;;;;; 0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; 097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; 097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; 097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;; 097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;; 097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;; 0980;BENGALI ANJI;Lo;0;L;;;;;N;;;;; 0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; 0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; 0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; 0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; 0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; 098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; 098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; 0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; 0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; 0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; 0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; 0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; 0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; 0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; 0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; 099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; 099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; 099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; 099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; 099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; 099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; 09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; 09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; 09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; 09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; 09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; 09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; 09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; 09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; 09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; 09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; 09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; 09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; 09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; 09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; 09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; 09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; 09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; 09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; 09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; 09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; 09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; 09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; 09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; 09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;; 09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; 09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; 09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; 09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;; 09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;; 09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; 09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;; 09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;; 09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;; 09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;; 09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;; 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; 0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; 0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; 0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; 0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; 0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; 0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; 0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; 0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; 0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; 0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; 0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; 0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; 0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; 0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; 0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; 0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; 0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; 0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; 0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; 0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; 0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; 0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; 0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; 0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; 0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; 0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; 0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; 0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; 0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; 0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; 0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; 0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; 0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; 0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; 0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;; 0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; 0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; 0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; 0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; 0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; 0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; 0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; 0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; 0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; 0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; 0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;; 0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; 0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; 0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; 0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; 0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; 0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; 0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; 0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; 0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; 0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; 0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; 0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; 0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; 0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; 0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; 0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; 0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; 0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; 0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; 0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; 0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; 0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; 0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; 0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; 0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; 0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; 0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; 0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; 0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; 0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; 0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; 0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; 0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; 0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; 0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; 0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; 0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; 0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; 0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; 0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; 0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; 0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; 0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; 0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; 0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; 0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; 0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; 0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; 0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; 0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; 0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; 0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; 0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; 0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; 0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; 0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; 0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; 0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; 0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; 0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; 0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; 0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; 0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; 0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; 0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; 0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; 0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; 0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; 0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; 0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; 0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; 0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; 0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; 0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; 0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; 0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; 0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;; 0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; 0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; 0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; 0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; 0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; 0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; 0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; 0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; 0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; 0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; 0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; 0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; 0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; 0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; 0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; 0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; 0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; 0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; 0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; 0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; 0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; 0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; 0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; 0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; 0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; 0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; 0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; 0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; 0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; 0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; 0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; 0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; 0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; 0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; 0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; 0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; 0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; 0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; 0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; 0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; 0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; 0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; 0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; 0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; 0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; 0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; 0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; 0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; 0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;; 0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; 0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; 0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; 0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; 0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; 0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; 0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;; 0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; 0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;; 0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;; 0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;; 0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;; 0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;; 0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;; 0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;; 0C00;TELUGU SIGN COMBINING CANDRABINDU ABOVE;Mn;0;NSM;;;;;N;;;;; 0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; 0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; 0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; 0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; 0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; 0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; 0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; 0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; 0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; 0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; 0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; 0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; 0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; 0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; 0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; 0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; 0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; 0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; 0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; 0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; 0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; 0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; 0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; 0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; 0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; 0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; 0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; 0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; 0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; 0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; 0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; 0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; 0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; 0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; 0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; 0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; 0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; 0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; 0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; 0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; 0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; 0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; 0C34;TELUGU LETTER LLLA;Lo;0;L;;;;;N;;;;; 0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; 0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; 0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; 0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; 0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; 0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; 0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; 0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; 0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; 0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; 0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;; 0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; 0C81;KANNADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; 0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; 0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; 0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; 0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; 0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; 0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; 0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; 0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; 0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; 0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; 0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; 0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; 0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; 0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; 0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; 0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; 0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; 0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; 0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; 0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; 0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; 0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; 0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; 0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; 0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; 0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; 0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; 0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; 0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; 0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; 0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; 0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; 0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; 0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; 0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; 0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; 0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; 0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; 0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; 0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; 0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; 0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; 0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; 0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; 0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;; 0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; 0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;; 0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; 0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; 0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; 0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; 0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; 0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; 0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; 0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; 0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; 0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; 0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; 0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; 0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; 0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; 0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; 0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; 0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; 0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; 0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; 0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; 0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; 0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; 0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; 0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; 0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; 0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; 0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; 0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; 0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; 0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; 0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; 0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; 0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; 0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; 0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; 0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;; 0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; 0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; 0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; 0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; 0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; 0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; 0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; 0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; 0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; 0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; 0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; 0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; 0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; 0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; 0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;; 0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; 0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; 0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; 0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; 0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;; 0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;; 0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;; 0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;; 0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; 0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; 0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; 0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; 0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; 0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; 0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; 0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; 0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; 0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; 0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; 0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; 0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; 0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; 0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; 0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; 0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; 0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; 0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; 0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; 0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; 0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; 0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; 0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; 0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; 0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; 0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; 0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; 0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; 0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; 0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; 0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; 0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; 0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; 0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; 0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; 0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; 0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DE6;SINHALA LITH DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0DE7;SINHALA LITH DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0DE8;SINHALA LITH DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0DE9;SINHALA LITH DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0DEA;SINHALA LITH DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0DEB;SINHALA LITH DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0DEC;SINHALA LITH DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0DED;SINHALA LITH DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0DEE;SINHALA LITH DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0DEF;SINHALA LITH DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; 0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; 0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; 0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; 0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; 0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; 0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; 0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; 0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; 0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; 0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; 0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; 0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; 0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; 0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; 0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; 0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; 0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; 0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; 0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; 0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; 0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; 0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; 0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; 0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; 0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; 0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; 0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; 0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; 0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; 0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; 0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; 0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; 0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; 0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; 0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; 0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; 0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; 0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; 0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; 0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; 0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; 0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; 0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; 0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; 0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; 0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; 0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;; 0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; 0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; 0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; 0E33;THAI CHARACTER SARA AM;Lo;0;L; 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; 0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; 0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; 0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; 0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;; 0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; 0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; 0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; 0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; 0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; 0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; 0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; 0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;; 0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;; 0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;; 0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;; 0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;; 0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; 0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; 0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; 0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; 0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; 0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;; 0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; 0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; 0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; 0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; 0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; 0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; 0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; 0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; 0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; 0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; 0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; 0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; 0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; 0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; 0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; 0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; 0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; 0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; 0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; 0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; 0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; 0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; 0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; 0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; 0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; 0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; 0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; 0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; 0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; 0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; 0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; 0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; 0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; 0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; 0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; 0EB3;LAO VOWEL SIGN AM;Lo;0;L; 0ECD 0EB2;;;;N;;;;; 0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; 0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; 0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; 0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; 0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; 0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; 0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; 0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; 0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; 0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; 0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; 0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; 0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; 0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; 0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; 0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; 0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; 0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0EDC;LAO HO NO;Lo;0;L; 0EAB 0E99;;;;N;;;;; 0EDD;LAO HO MO;Lo;0;L; 0EAB 0EA1;;;;N;;;;; 0EDE;LAO LETTER KHMU GO;Lo;0;L;;;;;N;;;;; 0EDF;LAO LETTER KHMU NYO;Lo;0;L;;;;;N;;;;; 0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; 0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;; 0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;; 0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;; 0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;; 0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;; 0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;; 0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;; 0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;; 0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;; 0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;; 0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L; 0F0B;;;;N;;;;; 0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;; 0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;; 0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;; 0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;; 0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;; 0F14;TIBETAN MARK GTER TSHEG;Po;0;L;;;;;N;TIBETAN COMMA;;;; 0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;; 0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;; 0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;; 0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;; 0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;; 0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;; 0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;; 0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;; 0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;; 0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;; 0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;; 0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; 0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; 0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; 0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; 0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; 0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; 0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; 0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; 0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; 0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; 0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;; 0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;; 0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;; 0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;; 0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;; 0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;; 0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;; 0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;; 0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;; 0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;; 0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;; 0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;; 0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; 0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; 0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; 0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; 0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; 0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; 0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; 0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; 0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; 0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; 0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; 0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; 0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; 0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; 0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; 0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; 0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; 0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; 0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; 0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; 0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; 0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; 0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; 0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; 0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; 0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; 0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; 0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; 0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; 0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; 0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; 0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; 0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;; 0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; 0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; 0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; 0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; 0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; 0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; 0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; 0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;; 0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;; 0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;; 0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; 0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; 0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; 0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; 0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; 0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; 0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM; 0FB2 0F81;;;;N;;;;; 0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; 0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM; 0FB3 0F81;;;;N;;;;; 0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; 0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; 0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; 0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; 0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;; 0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;; 0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; 0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; 0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;; 0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;; 0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; 0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; 0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;; 0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;; 0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;; 0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; 0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; 0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;; 0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;; 0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;; 0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; 0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; 0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; 0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; 0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; 0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; 0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; 0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; 0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; 0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; 0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; 0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; 0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; 0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; 0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; 0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; 0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; 0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; 0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; 0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; 0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; 0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; 0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; 0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; 0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; 0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; 0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; 0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; 0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; 0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; 0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;; 0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; 0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; 0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; 0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; 0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; 0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; 0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; 0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; 0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;; 0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;; 0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;; 0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;; 0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;; 0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; 0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; 0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;; 0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;; 0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;; 0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;; 0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;; 0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;; 0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;; 0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;; 0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;; 0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;; 0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;; 0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;; 0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;; 0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;; 0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;; 0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;; 0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;; 1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; 1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; 1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; 1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; 1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; 1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; 1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; 1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; 1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; 1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; 100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; 100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; 100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; 100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; 100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; 100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; 1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; 1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; 1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; 1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; 1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; 1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; 1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; 1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; 1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; 1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; 101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; 101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; 101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; 101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; 101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; 101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; 1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; 1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; 1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;; 1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; 1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; 1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; 1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; 1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; 1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;; 1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; 102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; 102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;; 1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;; 1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; 1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;; 103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; 103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;; 103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; 104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; 104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; 104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; 104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; 104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; 1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; 1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; 1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;; 105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;; 105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;; 105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;; 105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;; 105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;; 1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;; 1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;; 1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;; 1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;; 1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;; 1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;; 1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;; 1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;; 1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;; 106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;; 106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;; 106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;; 106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;; 106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;; 106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;; 1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;; 1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;; 1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;; 1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;; 1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;; 1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;; 1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;; 1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;; 1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;; 1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;; 107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;; 107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;; 107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;; 107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;; 107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;; 107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;; 1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;; 1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;; 1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;; 1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;; 1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;; 1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;; 1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;; 1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;; 108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;; 108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;; 108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;; 108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;; 108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;; 108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;; 1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;; 109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;; 109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;; 109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;; 109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;; 109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;; 10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00; 10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01; 10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02; 10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03; 10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04; 10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05; 10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06; 10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07; 10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08; 10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09; 10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A; 10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B; 10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C; 10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D; 10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E; 10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F; 10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10; 10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11; 10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12; 10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13; 10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14; 10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15; 10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16; 10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17; 10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18; 10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19; 10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A; 10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B; 10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C; 10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D; 10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E; 10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F; 10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20; 10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21; 10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22; 10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23; 10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24; 10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25; 10C7;GEORGIAN CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;2D27; 10CD;GEORGIAN CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;2D2D; 10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;; 10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;; 10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;; 10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;; 10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;; 10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;; 10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;; 10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;; 10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;; 10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;; 10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;; 10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;; 10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;; 10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;; 10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;; 10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;; 10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;; 10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;; 10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;; 10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;; 10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;; 10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;; 10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;; 10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;; 10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;; 10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;; 10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;; 10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;; 10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;; 10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;; 10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;; 10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;; 10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;; 10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;; 10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;; 10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;; 10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;; 10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;; 10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;; 10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;; 10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;; 10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;; 10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;; 10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L; 10DC;;;;N;;;;; 10FD;GEORGIAN LETTER AEN;Lo;0;L;;;;;N;;;;; 10FE;GEORGIAN LETTER HARD SIGN;Lo;0;L;;;;;N;;;;; 10FF;GEORGIAN LETTER LABIAL SIGN;Lo;0;L;;;;;N;;;;; 1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;; 1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; 1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;; 1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;; 1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;; 1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; 1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;; 110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; 110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;; 110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; 110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;; 1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; 1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; 111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; 1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; 1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; 1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; 1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; 112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; 112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; 112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; 1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; 1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; 1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; 1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; 113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; 113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; 113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; 113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; 113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; 1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; 1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; 1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; 1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; 1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; 114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; 114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; 114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; 114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; 114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; 1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; 1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; 1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; 1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;; 115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; 1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; 1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; 1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; 1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; 1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; 1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; 1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; 1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; 1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; 1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; 116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; 116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; 116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; 116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; 116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; 116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; 1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; 1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; 1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; 1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; 1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; 1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; 1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; 1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; 1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; 1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; 117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; 117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; 117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; 117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; 117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; 117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; 1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; 1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; 1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; 1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; 1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; 1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; 1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; 1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; 1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; 1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; 118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; 118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; 118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; 118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; 118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; 118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; 1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; 1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; 1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; 1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; 1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; 1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; 1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; 1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; 1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; 1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; 119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; 119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; 119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; 119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; 119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; 119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; 11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; 11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; 11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; 11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;; 11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;; 11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;; 11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;; 11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;; 11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;; 11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;; 11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; 11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; 11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; 11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; 11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;; 11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; 11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;; 11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;; 11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;; 11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;; 11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;; 11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;; 11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; 11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; 11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; 11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; 11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; 11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; 11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; 11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; 11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; 11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; 11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; 11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; 11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; 11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; 11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; 11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; 11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; 11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; 11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;; 11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;; 11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;; 11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;; 11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; 11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; 1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; 1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; 1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; 1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; 1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; 1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; 1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;; 1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; 1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; 120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; 120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; 120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; 120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; 120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; 120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; 1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; 1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; 1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; 1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; 1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; 1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; 1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; 1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; 1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; 1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; 121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; 121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; 121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; 121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; 121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; 121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; 1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; 1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; 1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; 1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; 1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; 1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; 1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; 1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; 1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; 1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; 122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; 122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; 122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; 122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; 122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; 122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; 1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; 1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; 1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; 1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; 1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; 1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; 1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; 1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; 1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; 1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; 123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; 123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; 123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; 123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; 123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; 123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; 1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; 1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; 1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; 1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; 1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; 1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; 1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; 1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;; 1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; 124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; 124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; 124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; 124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; 1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; 1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; 1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; 1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; 1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; 1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; 1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; 1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; 125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; 125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; 125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; 125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; 1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; 1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; 1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; 1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; 1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; 1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; 1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; 1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; 1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; 1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; 126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; 126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; 126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; 126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; 126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; 126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; 1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; 1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; 1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; 1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; 1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; 1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; 1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; 1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; 1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; 1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; 127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; 127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; 127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; 127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; 127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; 127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; 1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; 1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; 1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; 1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; 1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; 1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; 1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; 1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;; 1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; 128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; 128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; 128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; 128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; 1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; 1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; 1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; 1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; 1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; 1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; 1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; 1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; 1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; 1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; 129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; 129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; 129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; 129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; 129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; 129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; 12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; 12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; 12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; 12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; 12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; 12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; 12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; 12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; 12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; 12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; 12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; 12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; 12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; 12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; 12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; 12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;; 12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; 12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; 12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; 12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; 12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; 12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; 12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; 12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; 12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; 12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; 12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; 12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; 12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; 12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; 12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; 12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; 12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; 12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; 12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; 12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; 12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; 12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; 12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; 12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; 12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;; 12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; 12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; 12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; 12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; 12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; 12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; 12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; 12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; 12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; 12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; 12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; 12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; 12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; 12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; 12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; 12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; 12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; 12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; 12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; 12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; 12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; 12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; 12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; 12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; 12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; 12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; 12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; 12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; 12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; 12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; 12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;; 12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; 12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; 12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; 12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; 12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; 12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; 12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; 12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; 12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; 12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; 12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; 12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; 12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; 12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; 12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; 12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; 1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; 1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; 1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; 1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; 1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; 1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; 1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; 1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; 1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; 1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; 130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; 130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; 130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; 130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; 130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; 130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;; 1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; 1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; 1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; 1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; 1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; 1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; 1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; 131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; 131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; 131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; 131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; 131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; 131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;; 1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; 1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; 1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; 1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; 1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; 1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; 1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; 1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; 1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; 1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; 132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; 132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; 132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; 132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; 132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; 132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; 1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; 1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; 1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; 1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; 1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; 1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; 1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; 1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; 1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; 1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; 133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; 133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; 133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; 133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; 133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; 133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; 1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; 1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; 1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; 1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; 1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; 1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; 1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; 1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;; 1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; 1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; 134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; 134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; 134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; 134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; 134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; 134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; 1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; 1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; 1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; 1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; 1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; 1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; 1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; 1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; 1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; 1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; 135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; 135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; 135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; 135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; 1360;ETHIOPIC SECTION MARK;Po;0;L;;;;;N;;;;; 1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; 1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; 1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; 1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; 1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; 1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; 1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; 1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;; 136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;; 136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;; 136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;; 136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;; 136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;; 136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;; 1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;; 1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;; 1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; 1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; 137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;; 1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;; 1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;; 1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;; 1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;; 1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;; 1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;; 1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;; 1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;; 1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;; 138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;; 138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;; 138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;; 138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;; 138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;; 138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;; 1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;; 1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;; 1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;; 1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;; 1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;; 1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;; 1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;; 1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;; 1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;; 1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;; 13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;; 13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;; 13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;; 13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;; 13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;; 13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;; 13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;; 13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;; 13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;; 13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;; 13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;; 13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;; 13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;; 13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;; 13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;; 13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;; 13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;; 13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;; 13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;; 13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;; 13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;; 13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;; 13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;; 13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;; 13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;; 13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;; 13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;; 13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;; 13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;; 13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;; 13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;; 13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;; 13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;; 13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;; 13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;; 13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;; 13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;; 13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;; 13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;; 13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;; 13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;; 13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;; 13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;; 13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;; 13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;; 13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;; 13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;; 13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;; 13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;; 13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;; 13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;; 13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;; 13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;; 13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;; 13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;; 13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;; 13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;; 13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;; 13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;; 13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;; 13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;; 13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;; 13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;; 13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;; 13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;; 13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;; 13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;; 13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;; 13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;; 13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;; 13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;; 13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;; 13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;; 13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;; 13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;; 13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;; 13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;; 13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;; 13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;; 13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;; 13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;; 13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;; 13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;; 13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;; 13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;; 1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;; 1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; 1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; 1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; 1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; 1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; 1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; 1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; 1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; 1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; 140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; 140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; 140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; 140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; 140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; 140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; 1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; 1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; 1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; 1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; 1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; 1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; 1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; 1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; 1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; 1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; 141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; 141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; 141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; 141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; 141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; 1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; 1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; 1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; 1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; 1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; 1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; 1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; 1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; 1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; 1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; 142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; 142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; 142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; 142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; 142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; 142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; 1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; 1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; 1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; 1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; 1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; 1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; 1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; 1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; 1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; 1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; 143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; 143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; 143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; 143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; 143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; 143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; 1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; 1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; 1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; 1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; 1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; 1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; 1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; 1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; 1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; 1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; 144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; 144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; 144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; 144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; 144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; 144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; 1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; 1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; 1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; 1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; 1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; 1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; 1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; 1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; 1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; 1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; 145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; 145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; 145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; 145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; 145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; 145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; 1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; 1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; 1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; 1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; 1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; 1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; 1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; 1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; 1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; 1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; 146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; 146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; 146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; 146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; 146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; 146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; 1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; 1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; 1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; 1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; 1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; 1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; 1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; 1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; 1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; 1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; 147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; 147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; 147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; 147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; 147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; 147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; 1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; 1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; 1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; 1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; 1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; 1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; 1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; 1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; 1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; 1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; 148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; 148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; 148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; 148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; 148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; 148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; 1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; 1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; 1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; 1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; 1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; 1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; 1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; 1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; 1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; 1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; 149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; 149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; 149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; 149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; 149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; 149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; 14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; 14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; 14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; 14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; 14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; 14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; 14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; 14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; 14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; 14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; 14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; 14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; 14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; 14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; 14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; 14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; 14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; 14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; 14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; 14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; 14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; 14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; 14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; 14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; 14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; 14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; 14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; 14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; 14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; 14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; 14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; 14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; 14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; 14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; 14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; 14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; 14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; 14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; 14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; 14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; 14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; 14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; 14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; 14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; 14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; 14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; 14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; 14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; 14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; 14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; 14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; 14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; 14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; 14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; 14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; 14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; 14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; 14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; 14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; 14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; 14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; 14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; 14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; 14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; 14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; 14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; 14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; 14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; 14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; 14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; 14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; 14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; 14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; 14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; 14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; 14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; 14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; 14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; 14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; 14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; 14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; 14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; 14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; 14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; 14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; 14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; 14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; 14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; 14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; 14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; 14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; 14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; 14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; 14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; 14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; 14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; 1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; 1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; 1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; 1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; 1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; 1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; 1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; 1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; 1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; 1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; 150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; 150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; 150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; 150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; 150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; 150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; 1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; 1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; 1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; 1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; 1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; 1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; 1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; 1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; 1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; 1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; 151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; 151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; 151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; 151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; 151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; 151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; 1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; 1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; 1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; 1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; 1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; 1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; 1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; 1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; 1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; 1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; 152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; 152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; 152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; 152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; 152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; 152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; 1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; 1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; 1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; 1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; 1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; 1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; 1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; 1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; 1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; 1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; 153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; 153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; 153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; 153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; 153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; 153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; 1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; 1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; 1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; 1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; 1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; 1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; 1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; 1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; 1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; 1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; 154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; 154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; 154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; 154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; 154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; 154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; 1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; 1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; 1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; 1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; 1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; 1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; 1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; 1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; 1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; 1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; 155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; 155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; 155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; 155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; 155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; 155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; 1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; 1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; 1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; 1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; 1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; 1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; 1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; 1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; 1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; 1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; 156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; 156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; 156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; 156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; 156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; 156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; 1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; 1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; 1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; 1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; 1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; 1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; 1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; 1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; 1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; 1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; 157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; 157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; 157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; 157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; 157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; 157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; 1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; 1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; 1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; 1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; 1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; 1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; 1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; 1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; 1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; 1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; 158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; 158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; 158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; 158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; 158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; 158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; 1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; 1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; 1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; 1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; 1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; 1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; 1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; 1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; 1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; 1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; 159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; 159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; 159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; 159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; 159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; 159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; 15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; 15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; 15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; 15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; 15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; 15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; 15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; 15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; 15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; 15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; 15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; 15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; 15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; 15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; 15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; 15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; 15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; 15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; 15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; 15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; 15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; 15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; 15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; 15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; 15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; 15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; 15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; 15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; 15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; 15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; 15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; 15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; 15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; 15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; 15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; 15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; 15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; 15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; 15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; 15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; 15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; 15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; 15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; 15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; 15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; 15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; 15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; 15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; 15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; 15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; 15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; 15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; 15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; 15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; 15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; 15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; 15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; 15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; 15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; 15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; 15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; 15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; 15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; 15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; 15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; 15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; 15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; 15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; 15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; 15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; 15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; 15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; 15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; 15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; 15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; 15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; 15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; 15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; 15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; 15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; 15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; 15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; 15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; 15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; 15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; 15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; 15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; 15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; 15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; 15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; 15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; 15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; 15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; 15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; 15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; 15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; 1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; 1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; 1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; 1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; 1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; 1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; 1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; 1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; 1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; 1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; 160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; 160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; 160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; 160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; 160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; 160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; 1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; 1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; 1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; 1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; 1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; 1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; 1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; 1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; 1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; 1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; 161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; 161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; 161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; 161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; 161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; 161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; 1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; 1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; 1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; 1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; 1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; 1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; 1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; 1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; 1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; 1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; 162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; 162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; 162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; 162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; 162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; 162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; 1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; 1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; 1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; 1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; 1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; 1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; 1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; 1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; 1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; 1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; 163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; 163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; 163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; 163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; 163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; 163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; 1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; 1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; 1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; 1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; 1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; 1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; 1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; 1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; 1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; 1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; 164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; 164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; 164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; 164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; 164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; 164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; 1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; 1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; 1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; 1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; 1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; 1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; 1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; 1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; 1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; 1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; 165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; 165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; 165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; 165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; 165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; 165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; 1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; 1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; 1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; 1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; 1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; 1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; 1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; 1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; 1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; 1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; 166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; 166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; 166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; 166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;; 166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; 166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; 1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; 1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; 1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; 1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; 1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; 1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; 1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; 1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;; 1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;; 1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;; 167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;; 167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;; 167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;; 167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;; 167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;; 167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;; 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; 1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; 1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; 1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; 1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; 1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; 1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; 1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; 1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; 1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; 168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; 168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; 168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; 168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; 168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; 168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; 1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; 1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; 1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; 1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; 1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; 1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; 1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; 1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; 1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; 1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; 169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; 169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;; 169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;; 16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; 16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; 16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; 16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; 16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; 16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; 16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; 16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; 16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; 16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; 16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; 16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; 16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; 16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; 16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; 16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; 16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; 16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; 16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; 16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; 16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; 16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; 16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; 16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; 16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; 16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; 16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; 16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; 16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; 16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; 16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; 16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; 16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; 16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; 16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; 16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; 16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; 16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; 16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; 16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; 16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; 16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; 16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; 16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; 16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; 16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; 16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; 16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; 16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; 16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; 16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; 16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; 16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; 16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; 16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; 16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; 16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; 16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; 16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; 16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; 16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; 16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; 16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; 16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; 16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; 16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; 16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; 16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; 16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; 16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; 16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; 16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; 16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; 16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; 16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; 16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; 16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;; 16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;; 16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;; 16F1;RUNIC LETTER K;Lo;0;L;;;;;N;;;;; 16F2;RUNIC LETTER SH;Lo;0;L;;;;;N;;;;; 16F3;RUNIC LETTER OO;Lo;0;L;;;;;N;;;;; 16F4;RUNIC LETTER FRANKS CASKET OS;Lo;0;L;;;;;N;;;;; 16F5;RUNIC LETTER FRANKS CASKET IS;Lo;0;L;;;;;N;;;;; 16F6;RUNIC LETTER FRANKS CASKET EH;Lo;0;L;;;;;N;;;;; 16F7;RUNIC LETTER FRANKS CASKET AC;Lo;0;L;;;;;N;;;;; 16F8;RUNIC LETTER FRANKS CASKET AESC;Lo;0;L;;;;;N;;;;; 1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; 1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; 1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; 1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; 1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; 1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; 1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; 1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; 1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; 1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; 170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; 170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; 170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; 170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; 170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; 1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; 1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; 1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; 1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; 1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; 1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; 1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; 1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; 1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; 1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; 1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; 1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; 172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; 172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; 172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; 172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; 172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; 172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; 1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; 1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; 1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; 1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; 1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; 1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; 1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; 1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; 1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; 1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; 1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; 1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; 1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; 174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; 174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; 174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; 174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; 174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; 174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; 1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; 1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; 1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; 1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; 1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; 1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; 1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; 1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; 1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; 1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; 1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; 1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; 176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; 176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; 176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; 176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; 176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; 1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; 1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; 1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; 1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; 1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; 1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; 1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; 1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; 1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; 1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; 1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; 178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; 178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; 178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; 178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; 178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; 178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; 1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; 1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; 1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; 1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; 1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; 1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; 1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; 1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; 1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; 1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; 179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; 179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; 179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; 179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; 179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; 179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; 17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; 17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; 17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; 17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; 17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; 17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; 17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; 17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; 17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; 17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; 17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; 17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; 17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; 17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; 17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; 17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; 17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; 17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; 17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; 17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; 17B4;KHMER VOWEL INHERENT AQ;Mn;0;NSM;;;;;N;;;;; 17B5;KHMER VOWEL INHERENT AA;Mn;0;NSM;;;;;N;;;;; 17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; 17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; 17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; 17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; 17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; 17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; 17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; 17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; 17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; 17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; 17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; 17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; 17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; 17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; 17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; 17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; 17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; 17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; 17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; 17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; 17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; 17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; 17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; 17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; 17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; 17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; 17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;; 17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;; 17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;; 17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;; 17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;; 17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;; 17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;; 17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;; 17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;; 17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;; 17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;; 1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; 1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; 1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; 1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; 1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; 1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; 1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; 1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; 1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; 1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; 180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; 180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; 180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; 180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; 180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; 1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; 1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; 1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; 1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; 1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; 1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; 1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; 1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; 1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; 1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; 182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; 182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; 182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; 182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; 182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; 182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; 1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; 1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; 1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; 1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; 1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; 1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; 1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; 1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; 183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; 183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; 183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; 183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; 183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; 183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; 1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; 1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; 1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; 1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; 1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; 1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; 1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; 1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; 1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; 184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; 184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; 184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; 184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; 184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; 184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; 1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; 1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; 1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; 1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; 1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; 1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; 1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; 1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; 1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; 1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; 185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; 185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; 185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; 185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; 185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; 185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; 1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; 1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; 1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; 1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; 1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; 1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; 1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; 1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; 1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; 1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; 186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; 186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; 186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; 186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; 186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; 186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; 1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; 1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; 1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; 1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; 1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; 1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; 1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; 1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; 1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; 1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; 1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; 1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; 1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; 1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;; 1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;; 1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; 1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; 1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; 188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; 188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; 188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; 188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; 188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; 188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; 1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; 1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; 1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; 1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; 1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; 1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; 1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; 1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; 1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; 189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; 189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; 189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; 189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; 189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; 18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; 18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; 18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; 18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; 18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; 18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; 18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; 18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; 18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; 18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;; 18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;; 18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;; 18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;; 18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;; 18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;; 18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;; 18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;; 18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;; 18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;; 18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;; 18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;; 18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;; 18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;; 18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;; 18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;; 18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;; 18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;; 18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;; 18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;; 18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;; 18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;; 18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;; 18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;; 18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;; 18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;; 18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;; 18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;; 18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;; 18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;; 18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;; 18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;; 18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;; 18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;; 18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;; 18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;; 18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;; 18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;; 18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;; 18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;; 18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;; 18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;; 18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;; 18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;; 18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;; 18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;; 18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;; 18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;; 18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;; 18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;; 18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;; 18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;; 18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;; 18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;; 18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;; 18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;; 18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;; 18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;; 18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;; 18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;; 18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;; 18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;; 18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;; 18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;; 18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;; 18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;; 18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;; 18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;; 18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;; 18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;; 18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;; 1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;; 1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;; 1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;; 1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;; 1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;; 1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;; 1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;; 1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;; 1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;; 1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;; 190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;; 190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;; 190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;; 190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;; 190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;; 190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;; 1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;; 1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;; 1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;; 1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;; 1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;; 1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;; 1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;; 1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;; 1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;; 1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;; 191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;; 191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;; 191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;; 191D;LIMBU LETTER GYAN;Lo;0;L;;;;;N;;;;; 191E;LIMBU LETTER TRA;Lo;0;L;;;;;N;;;;; 1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; 1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;; 1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;; 1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;; 1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;; 1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;; 1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;; 1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;; 1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;; 1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;; 1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;; 193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;; 193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;; 1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;; 1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;; 1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;; 1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;; 1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;; 1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;; 1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;; 1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;; 1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;; 1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;; 1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;; 1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;; 195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;; 195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;; 195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;; 195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;; 195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;; 195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;; 1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;; 1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;; 1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;; 1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;; 1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;; 1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;; 1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;; 1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;; 1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;; 1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;; 196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;; 196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;; 196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;; 196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;; 1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;; 1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;; 1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;; 1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;; 1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;; 1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;; 1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;; 1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;; 1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;; 1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;; 1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;; 1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;; 1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;; 198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;; 198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;; 198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;; 1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;; 1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;; 1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;; 199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;; 199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;; 199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;; 199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;; 199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;; 19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;; 19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;; 19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;; 19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;; 19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;; 19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;; 19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;; 19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;; 19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;; 19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;; 19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;; 19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Mc;0;L;;;;;N;;;;; 19B1;NEW TAI LUE VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 19B2;NEW TAI LUE VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 19B3;NEW TAI LUE VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 19B4;NEW TAI LUE VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 19B5;NEW TAI LUE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 19B6;NEW TAI LUE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 19B7;NEW TAI LUE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 19B8;NEW TAI LUE VOWEL SIGN OA;Mc;0;L;;;;;N;;;;; 19B9;NEW TAI LUE VOWEL SIGN UE;Mc;0;L;;;;;N;;;;; 19BA;NEW TAI LUE VOWEL SIGN AY;Mc;0;L;;;;;N;;;;; 19BB;NEW TAI LUE VOWEL SIGN AAY;Mc;0;L;;;;;N;;;;; 19BC;NEW TAI LUE VOWEL SIGN UY;Mc;0;L;;;;;N;;;;; 19BD;NEW TAI LUE VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; 19BE;NEW TAI LUE VOWEL SIGN OAY;Mc;0;L;;;;;N;;;;; 19BF;NEW TAI LUE VOWEL SIGN UEY;Mc;0;L;;;;;N;;;;; 19C0;NEW TAI LUE VOWEL SIGN IY;Mc;0;L;;;;;N;;;;; 19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;; 19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;; 19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;; 19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;; 19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;; 19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;; 19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;; 19C8;NEW TAI LUE TONE MARK-1;Mc;0;L;;;;;N;;;;; 19C9;NEW TAI LUE TONE MARK-2;Mc;0;L;;;;;N;;;;; 19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;; 19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;; 19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;; 19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; 19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; 19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; 19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;; 19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;; 19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;; 19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;; 19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;; 19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;; 19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;; 19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;; 19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;; 19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;; 19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;; 19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;; 19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;; 19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;; 19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;; 19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;; 19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;; 19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;; 19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;; 19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;; 19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;; 19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;; 19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;; 19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;; 19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;; 19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;; 19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;; 19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;; 19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;; 1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;; 1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;; 1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;; 1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;; 1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;; 1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;; 1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;; 1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1A1B;BUGINESE VOWEL SIGN AE;Mn;0;NSM;;;;;N;;;;; 1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;; 1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;; 1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;; 1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;; 1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;; 1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;; 1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;; 1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;; 1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;; 1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;; 1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;; 1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;; 1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;; 1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;; 1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;; 1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;; 1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;; 1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;; 1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;; 1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;; 1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;; 1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;; 1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;; 1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;; 1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;; 1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;; 1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;; 1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;; 1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;; 1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;; 1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;; 1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;; 1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;; 1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;; 1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;; 1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;; 1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;; 1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;; 1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;; 1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;; 1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;; 1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;; 1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;; 1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;; 1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;; 1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;; 1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;; 1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;; 1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; 1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;; 1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; 1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;; 1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;; 1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;; 1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;; 1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;; 1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;; 1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;; 1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;; 1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;; 1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;; 1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;; 1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;; 1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;; 1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;; 1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;; 1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;; 1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;; 1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;; 1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;; 1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;; 1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;; 1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;; 1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;; 1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;; 1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;; 1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;; 1AB0;COMBINING DOUBLED CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;;;;; 1AB1;COMBINING DIAERESIS-RING;Mn;230;NSM;;;;;N;;;;; 1AB2;COMBINING INFINITY;Mn;230;NSM;;;;;N;;;;; 1AB3;COMBINING DOWNWARDS ARROW;Mn;230;NSM;;;;;N;;;;; 1AB4;COMBINING TRIPLE DOT;Mn;230;NSM;;;;;N;;;;; 1AB5;COMBINING X-X BELOW;Mn;220;NSM;;;;;N;;;;; 1AB6;COMBINING WIGGLY LINE BELOW;Mn;220;NSM;;;;;N;;;;; 1AB7;COMBINING OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; 1AB8;COMBINING DOUBLE OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; 1AB9;COMBINING LIGHT CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; 1ABA;COMBINING STRONG CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; 1ABB;COMBINING PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; 1ABC;COMBINING DOUBLE PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; 1ABD;COMBINING PARENTHESES BELOW;Mn;220;NSM;;;;;N;;;;; 1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; 1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; 1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; 1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; 1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;; 1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;; 1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;; 1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;; 1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;; 1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;; 1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;; 1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;; 1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;; 1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;; 1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;; 1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;; 1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;; 1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;; 1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;; 1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;; 1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;; 1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;; 1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;; 1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;; 1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;; 1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;; 1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;; 1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;; 1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;; 1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;; 1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;; 1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;; 1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;; 1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;; 1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;; 1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;; 1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; 1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;; 1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;; 1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;; 1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;; 1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;; 1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; 1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;; 1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;; 1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;; 1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; 1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;; 1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;; 1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;; 1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;; 1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;; 1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;; 1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; 1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; 1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; 1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;; 1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;; 1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;; 1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;; 1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;; 1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;; 1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;; 1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;; 1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;; 1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;; 1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;; 1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;; 1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;; 1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;; 1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;; 1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;; 1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;; 1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;; 1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;; 1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;; 1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;; 1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;; 1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;; 1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;; 1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;; 1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;; 1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;; 1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;; 1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;; 1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; 1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; 1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; 1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; 1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; 1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; 1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;; 1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;; 1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;; 1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;; 1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;; 1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;; 1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;; 1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;; 1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;; 1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;; 1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;; 1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;; 1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;; 1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;; 1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;; 1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;; 1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;; 1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;; 1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;; 1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;; 1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;; 1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;; 1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;; 1BAB;SUNDANESE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1BAC;SUNDANESE CONSONANT SIGN PASANGAN MA;Mn;0;NSM;;;;;N;;;;; 1BAD;SUNDANESE CONSONANT SIGN PASANGAN WA;Mn;0;NSM;;;;;N;;;;; 1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;; 1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;; 1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1BBA;SUNDANESE AVAGRAHA;Lo;0;L;;;;;N;;;;; 1BBB;SUNDANESE LETTER REU;Lo;0;L;;;;;N;;;;; 1BBC;SUNDANESE LETTER LEU;Lo;0;L;;;;;N;;;;; 1BBD;SUNDANESE LETTER BHA;Lo;0;L;;;;;N;;;;; 1BBE;SUNDANESE LETTER FINAL K;Lo;0;L;;;;;N;;;;; 1BBF;SUNDANESE LETTER FINAL M;Lo;0;L;;;;;N;;;;; 1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;; 1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;; 1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;; 1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;; 1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;; 1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;; 1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;; 1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;; 1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;; 1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;; 1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;; 1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;; 1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;; 1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;; 1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;; 1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;; 1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;; 1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;; 1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;; 1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;; 1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;; 1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;; 1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;; 1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;; 1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;; 1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;; 1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;; 1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;; 1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;; 1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;; 1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;; 1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;; 1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;; 1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;; 1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;; 1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;; 1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;; 1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;; 1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;; 1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;; 1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;; 1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;; 1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;; 1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; 1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;; 1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;; 1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;; 1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;; 1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;; 1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;; 1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;; 1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; 1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; 1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; 1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;; 1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;; 1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;; 1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;; 1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;; 1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;; 1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;; 1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;; 1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;; 1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;; 1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;; 1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;; 1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;; 1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;; 1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;; 1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;; 1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;; 1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;; 1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;; 1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;; 1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;; 1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;; 1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;; 1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;; 1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;; 1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;; 1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;; 1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;; 1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;; 1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;; 1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;; 1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;; 1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;; 1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; 1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; 1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; 1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; 1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;; 1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; 1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;; 1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;; 1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;; 1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;; 1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;; 1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;; 1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;; 1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;; 1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;; 1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;; 1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;; 1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;; 1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;; 1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;; 1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;; 1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;; 1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;; 1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;; 1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;; 1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;; 1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;; 1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;; 1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;; 1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;; 1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;; 1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;; 1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;; 1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;; 1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;; 1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;; 1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;; 1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;; 1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;; 1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;; 1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;; 1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;; 1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;; 1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;; 1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;; 1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;; 1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;; 1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;; 1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;; 1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;; 1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; 1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; 1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; 1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;; 1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;; 1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;; 1CC3;SUNDANESE PUNCTUATION BINDU CAKRA;Po;0;L;;;;;N;;;;; 1CC4;SUNDANESE PUNCTUATION BINDU LEU SATANGA;Po;0;L;;;;;N;;;;; 1CC5;SUNDANESE PUNCTUATION BINDU KA SATANGA;Po;0;L;;;;;N;;;;; 1CC6;SUNDANESE PUNCTUATION BINDU DA SATANGA;Po;0;L;;;;;N;;;;; 1CC7;SUNDANESE PUNCTUATION BINDU BA SATANGA;Po;0;L;;;;;N;;;;; 1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;; 1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;; 1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;; 1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;; 1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;; 1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;; 1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;; 1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;; 1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; 1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;; 1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;; 1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;; 1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;; 1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;; 1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;; 1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;; 1CF3;VEDIC SIGN ROTATED ARDHAVISARGA;Mc;0;L;;;;;N;;;;; 1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; 1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;; 1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;; 1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;; 1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;; 1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;; 1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;; 1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;; 1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;; 1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;; 1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;; 1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;; 1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;; 1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;; 1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;; 1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;; 1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;; 1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;; 1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;; 1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;; 1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;; 1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;; 1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;; 1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;; 1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;; 1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;; 1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;; 1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;; 1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;; 1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;; 1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;; 1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;; 1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;; 1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;; 1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;; 1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;; 1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;; 1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;; 1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;; 1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;; 1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;; 1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;; 1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;; 1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;; 1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L; 0041;;;;N;;;;; 1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L; 00C6;;;;N;;;;; 1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L; 0042;;;;N;;;;; 1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;; 1D30;MODIFIER LETTER CAPITAL D;Lm;0;L; 0044;;;;N;;;;; 1D31;MODIFIER LETTER CAPITAL E;Lm;0;L; 0045;;;;N;;;;; 1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L; 018E;;;;N;;;;; 1D33;MODIFIER LETTER CAPITAL G;Lm;0;L; 0047;;;;N;;;;; 1D34;MODIFIER LETTER CAPITAL H;Lm;0;L; 0048;;;;N;;;;; 1D35;MODIFIER LETTER CAPITAL I;Lm;0;L; 0049;;;;N;;;;; 1D36;MODIFIER LETTER CAPITAL J;Lm;0;L; 004A;;;;N;;;;; 1D37;MODIFIER LETTER CAPITAL K;Lm;0;L; 004B;;;;N;;;;; 1D38;MODIFIER LETTER CAPITAL L;Lm;0;L; 004C;;;;N;;;;; 1D39;MODIFIER LETTER CAPITAL M;Lm;0;L; 004D;;;;N;;;;; 1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L; 004E;;;;N;;;;; 1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;; 1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L; 004F;;;;N;;;;; 1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L; 0222;;;;N;;;;; 1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L; 0050;;;;N;;;;; 1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L; 0052;;;;N;;;;; 1D40;MODIFIER LETTER CAPITAL T;Lm;0;L; 0054;;;;N;;;;; 1D41;MODIFIER LETTER CAPITAL U;Lm;0;L; 0055;;;;N;;;;; 1D42;MODIFIER LETTER CAPITAL W;Lm;0;L; 0057;;;;N;;;;; 1D43;MODIFIER LETTER SMALL A;Lm;0;L; 0061;;;;N;;;;; 1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L; 0250;;;;N;;;;; 1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L; 0251;;;;N;;;;; 1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L; 1D02;;;;N;;;;; 1D47;MODIFIER LETTER SMALL B;Lm;0;L; 0062;;;;N;;;;; 1D48;MODIFIER LETTER SMALL D;Lm;0;L; 0064;;;;N;;;;; 1D49;MODIFIER LETTER SMALL E;Lm;0;L; 0065;;;;N;;;;; 1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L; 0259;;;;N;;;;; 1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L; 025B;;;;N;;;;; 1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L; 025C;;;;N;;;;; 1D4D;MODIFIER LETTER SMALL G;Lm;0;L; 0067;;;;N;;;;; 1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;; 1D4F;MODIFIER LETTER SMALL K;Lm;0;L; 006B;;;;N;;;;; 1D50;MODIFIER LETTER SMALL M;Lm;0;L; 006D;;;;N;;;;; 1D51;MODIFIER LETTER SMALL ENG;Lm;0;L; 014B;;;;N;;;;; 1D52;MODIFIER LETTER SMALL O;Lm;0;L; 006F;;;;N;;;;; 1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L; 0254;;;;N;;;;; 1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L; 1D16;;;;N;;;;; 1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L; 1D17;;;;N;;;;; 1D56;MODIFIER LETTER SMALL P;Lm;0;L; 0070;;;;N;;;;; 1D57;MODIFIER LETTER SMALL T;Lm;0;L; 0074;;;;N;;;;; 1D58;MODIFIER LETTER SMALL U;Lm;0;L; 0075;;;;N;;;;; 1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L; 1D1D;;;;N;;;;; 1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L; 026F;;;;N;;;;; 1D5B;MODIFIER LETTER SMALL V;Lm;0;L; 0076;;;;N;;;;; 1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L; 1D25;;;;N;;;;; 1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L; 03B2;;;;N;;;;; 1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L; 03B3;;;;N;;;;; 1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L; 03B4;;;;N;;;;; 1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L; 03C6;;;;N;;;;; 1D61;MODIFIER LETTER SMALL CHI;Lm;0;L; 03C7;;;;N;;;;; 1D62;LATIN SUBSCRIPT SMALL LETTER I;Lm;0;L; 0069;;;;N;;;;; 1D63;LATIN SUBSCRIPT SMALL LETTER R;Lm;0;L; 0072;;;;N;;;;; 1D64;LATIN SUBSCRIPT SMALL LETTER U;Lm;0;L; 0075;;;;N;;;;; 1D65;LATIN SUBSCRIPT SMALL LETTER V;Lm;0;L; 0076;;;;N;;;;; 1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Lm;0;L; 03B2;;;;N;;;;; 1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Lm;0;L; 03B3;;;;N;;;;; 1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Lm;0;L; 03C1;;;;N;;;;; 1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Lm;0;L; 03C6;;;;N;;;;; 1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Lm;0;L; 03C7;;;;N;;;;; 1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;; 1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;; 1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L; 043D;;;;N;;;;; 1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D 1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;; 1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63 1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;; 1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;; 1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L; 0252;;;;N;;;;; 1D9C;MODIFIER LETTER SMALL C;Lm;0;L; 0063;;;;N;;;;; 1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L; 0255;;;;N;;;;; 1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L; 00F0;;;;N;;;;; 1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L; 025C;;;;N;;;;; 1DA0;MODIFIER LETTER SMALL F;Lm;0;L; 0066;;;;N;;;;; 1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L; 025F;;;;N;;;;; 1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L; 0261;;;;N;;;;; 1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L; 0265;;;;N;;;;; 1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L; 0268;;;;N;;;;; 1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L; 0269;;;;N;;;;; 1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L; 026A;;;;N;;;;; 1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L; 1D7B;;;;N;;;;; 1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L; 029D;;;;N;;;;; 1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L; 026D;;;;N;;;;; 1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L; 1D85;;;;N;;;;; 1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L; 029F;;;;N;;;;; 1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L; 0271;;;;N;;;;; 1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L; 0270;;;;N;;;;; 1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L; 0272;;;;N;;;;; 1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L; 0273;;;;N;;;;; 1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L; 0274;;;;N;;;;; 1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L; 0275;;;;N;;;;; 1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L; 0278;;;;N;;;;; 1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L; 0282;;;;N;;;;; 1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L; 0283;;;;N;;;;; 1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L; 01AB;;;;N;;;;; 1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L; 0289;;;;N;;;;; 1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L; 028A;;;;N;;;;; 1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L; 1D1C;;;;N;;;;; 1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L; 028B;;;;N;;;;; 1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L; 028C;;;;N;;;;; 1DBB;MODIFIER LETTER SMALL Z;Lm;0;L; 007A;;;;N;;;;; 1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L; 0290;;;;N;;;;; 1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L; 0291;;;;N;;;;; 1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L; 0292;;;;N;;;;; 1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L; 03B8;;;;N;;;;; 1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;; 1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;; 1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;; 1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;; 1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;; 1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;; 1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;; 1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;; 1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;; 1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;; 1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;; 1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;; 1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;; 1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;; 1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;; 1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;; 1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;; 1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;; 1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;; 1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;; 1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;; 1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;; 1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;; 1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;; 1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; 1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; 1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; 1DE7;COMBINING LATIN SMALL LETTER ALPHA;Mn;230;NSM;;;;;N;;;;; 1DE8;COMBINING LATIN SMALL LETTER B;Mn;230;NSM;;;;;N;;;;; 1DE9;COMBINING LATIN SMALL LETTER BETA;Mn;230;NSM;;;;;N;;;;; 1DEA;COMBINING LATIN SMALL LETTER SCHWA;Mn;230;NSM;;;;;N;;;;; 1DEB;COMBINING LATIN SMALL LETTER F;Mn;230;NSM;;;;;N;;;;; 1DEC;COMBINING LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Mn;230;NSM;;;;;N;;;;; 1DED;COMBINING LATIN SMALL LETTER O WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; 1DEE;COMBINING LATIN SMALL LETTER P;Mn;230;NSM;;;;;N;;;;; 1DEF;COMBINING LATIN SMALL LETTER ESH;Mn;230;NSM;;;;;N;;;;; 1DF0;COMBINING LATIN SMALL LETTER U WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; 1DF1;COMBINING LATIN SMALL LETTER W;Mn;230;NSM;;;;;N;;;;; 1DF2;COMBINING LATIN SMALL LETTER A WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; 1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; 1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; 1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; 1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; 1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; 1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; 1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A 1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; 1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C 1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; 1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E 1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; 1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; 1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; 1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; 1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; 1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; 1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A 1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; 1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C 1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; 1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E 1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; 1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; 1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; 1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; 1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; 1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; 1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A 1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; 1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C 1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; 1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E 1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; 1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; 1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; 1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; 1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; 1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; 1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A 1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; 1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C 1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; 1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E 1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; 1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; 1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; 1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; 1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; 1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; 1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A 1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; 1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C 1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; 1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E 1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; 1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; 1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; 1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; 1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; 1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; 1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A 1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; 1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C 1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; 1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E 1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; 1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; 1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; 1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; 1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; 1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; 1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A 1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; 1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C 1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; 1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E 1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; 1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; 1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; 1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; 1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; 1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; 1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A 1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; 1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C 1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; 1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E 1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; 1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; 1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; 1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; 1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; 1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; 1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A 1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; 1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C 1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; 1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E 1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; 1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; 1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; 1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; 1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; 1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; 1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; 1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L; 0061 02BE;;;;N;;;;; 1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;; 1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;; 1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF; 1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;; 1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; 1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; 1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; 1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; 1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; 1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; 1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA 1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; 1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC 1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; 1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE 1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; 1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; 1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; 1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; 1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; 1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; 1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA 1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; 1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC 1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; 1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE 1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; 1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; 1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; 1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; 1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; 1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; 1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA 1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC 1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; 1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE 1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; 1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; 1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; 1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; 1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; 1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA 1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; 1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC 1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; 1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE 1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; 1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; 1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; 1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; 1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; 1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; 1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA 1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; 1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC 1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; 1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE 1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; 1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; 1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; 1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; 1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; 1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB; 1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA 1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD; 1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC 1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF; 1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE 1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A 1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B 1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C 1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D 1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E 1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F 1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; 1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; 1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; 1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; 1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; 1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; 1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; 1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; 1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A 1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B 1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C 1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D 1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; 1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; 1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; 1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; 1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; 1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; 1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A 1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B 1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C 1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D 1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E 1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F 1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; 1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; 1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; 1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; 1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; 1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; 1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; 1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; 1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A 1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B 1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C 1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D 1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E 1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F 1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; 1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; 1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; 1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; 1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; 1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; 1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; 1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; 1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A 1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B 1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C 1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D 1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; 1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; 1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; 1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; 1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; 1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; 1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; 1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; 1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B 1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; 1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D 1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; 1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F 1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; 1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; 1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; 1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; 1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A 1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B 1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C 1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D 1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E 1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F 1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; 1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; 1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; 1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; 1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; 1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; 1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; 1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; 1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA 1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB 1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA 1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB 1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA 1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB 1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA 1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB 1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA 1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB 1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A 1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B 1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C 1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D 1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E 1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F 1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; 1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; 1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; 1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; 1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; 1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; 1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; 1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; 1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A 1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B 1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C 1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D 1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E 1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F 1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; 1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; 1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; 1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; 1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; 1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; 1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; 1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; 1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA 1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB 1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC 1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD 1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE 1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF 1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; 1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; 1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; 1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; 1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; 1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; 1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; 1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; 1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; 1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC 1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; 1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; 1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; 1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; 1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; 1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; 1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; 1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; 1FBD;GREEK KORONIS;Sk;0;ON; 0020 0313;;;;N;;;;; 1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 1FBF;GREEK PSILI;Sk;0;ON; 0020 0313;;;;N;;;;; 1FC0;GREEK PERISPOMENI;Sk;0;ON; 0020 0342;;;;N;;;;; 1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; 1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; 1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC 1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; 1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; 1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; 1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; 1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; 1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; 1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; 1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; 1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; 1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; 1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; 1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; 1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; 1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; 1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; 1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; 1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; 1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; 1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; 1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; 1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; 1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; 1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; 1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; 1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; 1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC 1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; 1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; 1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; 1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; 1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; 1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; 1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; 1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; 1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; 1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; 1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; 1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC 1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; 1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; 1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; 1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; 1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; 1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; 1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; 1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; 1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; 1FFE;GREEK DASIA;Sk;0;ON; 0020 0314;;;;N;;;;; 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; 2002;EN SPACE;Zs;0;WS; 0020;;;;N;;;;; 2003;EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2004;THREE-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2005;FOUR-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2006;SIX-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; 2007;FIGURE SPACE;Zs;0;WS; 0020;;;;N;;;;; 2008;PUNCTUATION SPACE;Zs;0;WS; 0020;;;;N;;;;; 2009;THIN SPACE;Zs;0;WS; 0020;;;;N;;;;; 200A;HAIR SPACE;Zs;0;WS; 0020;;;;N;;;;; 200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;; 200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; 200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; 200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; 200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; 2010;HYPHEN;Pd;0;ON;;;;;N;;;;; 2011;NON-BREAKING HYPHEN;Pd;0;ON; 2010;;;;N;;;;; 2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; 2013;EN DASH;Pd;0;ON;;;;;N;;;;; 2014;EM DASH;Pd;0;ON;;;;;N;;;;; 2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; 2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; 2017;DOUBLE LOW LINE;Po;0;ON; 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; 2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; 2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; 201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; 201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; 201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; 201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; 201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; 201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; 2020;DAGGER;Po;0;ON;;;;;N;;;;; 2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; 2022;BULLET;Po;0;ON;;;;;N;;;;; 2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; 2024;ONE DOT LEADER;Po;0;ON; 002E;;;;N;;;;; 2025;TWO DOT LEADER;Po;0;ON; 002E 002E;;;;N;;;;; 2026;HORIZONTAL ELLIPSIS;Po;0;ON; 002E 002E 002E;;;;N;;;;; 2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; 202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; 202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; 202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; 202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; 202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; 202F;NARROW NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;;;;; 2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 2032;PRIME;Po;0;ET;;;;;N;;;;; 2033;DOUBLE PRIME;Po;0;ET; 2032 2032;;;;N;;;;; 2034;TRIPLE PRIME;Po;0;ET; 2032 2032 2032;;;;N;;;;; 2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; 2036;REVERSED DOUBLE PRIME;Po;0;ON; 2035 2035;;;;N;;;;; 2037;REVERSED TRIPLE PRIME;Po;0;ON; 2035 2035 2035;;;;N;;;;; 2038;CARET;Po;0;ON;;;;;N;;;;; 2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; 203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; 203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; 203C;DOUBLE EXCLAMATION MARK;Po;0;ON; 0021 0021;;;;N;;;;; 203D;INTERROBANG;Po;0;ON;;;;;N;;;;; 203E;OVERLINE;Po;0;ON; 0020 0305;;;;N;SPACING OVERSCORE;;;; 203F;UNDERTIE;Pc;0;ON;;;;;N;;;;; 2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; 2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; 2042;ASTERISM;Po;0;ON;;;;;N;;;;; 2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; 2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;; 2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; 2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; 2047;DOUBLE QUESTION MARK;Po;0;ON; 003F 003F;;;;N;;;;; 2048;QUESTION EXCLAMATION MARK;Po;0;ON; 003F 0021;;;;N;;;;; 2049;EXCLAMATION QUESTION MARK;Po;0;ON; 0021 003F;;;;N;;;;; 204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; 204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; 204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; 204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; 2050;CLOSE UP;Po;0;ON;;;;;N;;;;; 2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; 2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2053;SWUNG DASH;Po;0;ON;;;;;N;;;;; 2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;; 2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;; 2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2057;QUADRUPLE PRIME;Po;0;ON; 2032 2032 2032 2032;;;;N;;;;; 2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;; 205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;; 205D;TRICOLON;Po;0;ON;;;;;N;;;;; 205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;; 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS; 0020;;;;N;;;;; 2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; 2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; 2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; 2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; 2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;; 2066;LEFT-TO-RIGHT ISOLATE;Cf;0;LRI;;;;;N;;;;; 2067;RIGHT-TO-LEFT ISOLATE;Cf;0;RLI;;;;;N;;;;; 2068;FIRST STRONG ISOLATE;Cf;0;FSI;;;;;N;;;;; 2069;POP DIRECTIONAL ISOLATE;Cf;0;PDI;;;;;N;;;;; 206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 2070;SUPERSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; 2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L; 0069;;;;N;;;;; 2074;SUPERSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; 2075;SUPERSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; 2076;SUPERSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;; 2077;SUPERSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; 2078;SUPERSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; 2079;SUPERSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;; 207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; 207B;SUPERSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; 207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; 207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; 207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; 2080;SUBSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;; 2081;SUBSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;; 2082;SUBSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;; 2083;SUBSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;; 2084;SUBSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;; 2085;SUBSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;; 2086;SUBSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;; 2087;SUBSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; 2088;SUBSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; 2089;SUBSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;; 208A;SUBSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; 208B;SUBSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; 208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; 208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; 208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; 2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L; 0061;;;;N;;;;; 2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L; 0065;;;;N;;;;; 2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L; 006F;;;;N;;;;; 2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L; 0078;;;;N;;;;; 2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L; 0259;;;;N;;;;; 2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L; 0068;;;;N;;;;; 2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L; 006B;;;;N;;;;; 2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L; 006C;;;;N;;;;; 2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L; 006D;;;;N;;;;; 2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; 209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L; 0070;;;;N;;;;; 209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L; 0073;;;;N;;;;; 209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L; 0074;;;;N;;;;; 20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; 20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; 20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; 20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; 20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; 20A8;RUPEE SIGN;Sc;0;ET; 0052 0073;;;;N;;;;; 20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; 20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; 20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; 20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; 20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; 20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; 20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; 20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; 20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; 20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;; 20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;; 20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;; 20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;; 20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; 20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; 20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; 20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 20BA;TURKISH LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20BB;NORDIC MARK SIGN;Sc;0;ET;;;;;N;;;;; 20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; 20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; 20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; 20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; 20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; 20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; 20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; 20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; 20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; 20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; 20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; 20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; 20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; 20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; 20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; 20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; 20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; 20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; 20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; 20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; 20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; 20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;; 2100;ACCOUNT OF;So;0;ON; 0061 002F 0063;;;;N;;;;; 2101;ADDRESSED TO THE SUBJECT;So;0;ON; 0061 002F 0073;;;;N;;;;; 2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L; 0043;;;;N;DOUBLE-STRUCK C;;;; 2103;DEGREE CELSIUS;So;0;ON; 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; 2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; 2105;CARE OF;So;0;ON; 0063 002F 006F;;;;N;;;;; 2106;CADA UNA;So;0;ON; 0063 002F 0075;;;;N;;;;; 2107;EULER CONSTANT;Lu;0;L; 0190;;;;N;EULERS;;;; 2108;SCRUPLE;So;0;ON;;;;;N;;;;; 2109;DEGREE FAHRENHEIT;So;0;ON; 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; 210A;SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 210B;SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;SCRIPT H;;;; 210C;BLACK-LETTER CAPITAL H;Lu;0;L; 0048;;;;N;BLACK-LETTER H;;;; 210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L; 0048;;;;N;DOUBLE-STRUCK H;;;; 210E;PLANCK CONSTANT;Ll;0;L; 0068;;;;N;;;;; 210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L; 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; 2110;SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;SCRIPT I;;;; 2111;BLACK-LETTER CAPITAL I;Lu;0;L; 0049;;;;N;BLACK-LETTER I;;;; 2112;SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;SCRIPT L;;;; 2113;SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; 2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L; 004E;;;;N;DOUBLE-STRUCK N;;;; 2116;NUMERO SIGN;So;0;ON; 004E 006F;;;;N;NUMERO;;;; 2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; 2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;; 2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L; 0050;;;;N;DOUBLE-STRUCK P;;;; 211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L; 0051;;;;N;DOUBLE-STRUCK Q;;;; 211B;SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;SCRIPT R;;;; 211C;BLACK-LETTER CAPITAL R;Lu;0;L; 0052;;;;N;BLACK-LETTER R;;;; 211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L; 0052;;;;N;DOUBLE-STRUCK R;;;; 211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; 211F;RESPONSE;So;0;ON;;;;;N;;;;; 2120;SERVICE MARK;So;0;ON; 0053 004D;;;;N;;;;; 2121;TELEPHONE SIGN;So;0;ON; 0054 0045 004C;;;;N;T E L SYMBOL;;;; 2122;TRADE MARK SIGN;So;0;ON; 0054 004D;;;;N;TRADEMARK;;;; 2123;VERSICLE;So;0;ON;;;;;N;;;;; 2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L; 005A;;;;N;DOUBLE-STRUCK Z;;;; 2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; 2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; 2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; 2128;BLACK-LETTER CAPITAL Z;Lu;0;L; 005A;;;;N;BLACK-LETTER Z;;;; 2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; 212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; 212C;SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;SCRIPT B;;;; 212D;BLACK-LETTER CAPITAL C;Lu;0;L; 0043;;;;N;BLACK-LETTER C;;;; 212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; 212F;SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 2130;SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;SCRIPT E;;;; 2131;SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;SCRIPT F;;;; 2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E; 2133;SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;SCRIPT M;;;; 2134;SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 2135;ALEF SYMBOL;Lo;0;L; 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; 2136;BET SYMBOL;Lo;0;L; 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; 2137;GIMEL SYMBOL;Lo;0;L; 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; 2138;DALET SYMBOL;Lo;0;L; 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; 2139;INFORMATION SOURCE;Ll;0;L; 0069;;;;N;;;;; 213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; 213B;FACSIMILE SIGN;So;0;ON; 0046 0041 0058;;;;N;;;;; 213C;DOUBLE-STRUCK SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON; 2211;;;;Y;;;;; 2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; 2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; 2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; 214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; 214C;PER SIGN;So;0;ON;;;;;N;;;;; 214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;; 214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132 214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;; 2150;VULGAR FRACTION ONE SEVENTH;No;0;ON; 0031 2044 0037;;;1/7;N;;;;; 2151;VULGAR FRACTION ONE NINTH;No;0;ON; 0031 2044 0039;;;1/9;N;;;;; 2152;VULGAR FRACTION ONE TENTH;No;0;ON; 0031 2044 0031 0030;;;1/10;N;;;;; 2153;VULGAR FRACTION ONE THIRD;No;0;ON; 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; 2154;VULGAR FRACTION TWO THIRDS;No;0;ON; 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; 2155;VULGAR FRACTION ONE FIFTH;No;0;ON; 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; 2156;VULGAR FRACTION TWO FIFTHS;No;0;ON; 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; 2157;VULGAR FRACTION THREE FIFTHS;No;0;ON; 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; 2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON; 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; 2159;VULGAR FRACTION ONE SIXTH;No;0;ON; 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; 215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON; 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; 215B;VULGAR FRACTION ONE EIGHTH;No;0;ON; 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; 215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON; 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; 215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON; 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; 215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON; 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; 215F;FRACTION NUMERATOR ONE;No;0;ON; 0031 2044;;;1;N;;;;; 2160;ROMAN NUMERAL ONE;Nl;0;L; 0049;;;1;N;;;;2170; 2161;ROMAN NUMERAL TWO;Nl;0;L; 0049 0049;;;2;N;;;;2171; 2162;ROMAN NUMERAL THREE;Nl;0;L; 0049 0049 0049;;;3;N;;;;2172; 2163;ROMAN NUMERAL FOUR;Nl;0;L; 0049 0056;;;4;N;;;;2173; 2164;ROMAN NUMERAL FIVE;Nl;0;L; 0056;;;5;N;;;;2174; 2165;ROMAN NUMERAL SIX;Nl;0;L; 0056 0049;;;6;N;;;;2175; 2166;ROMAN NUMERAL SEVEN;Nl;0;L; 0056 0049 0049;;;7;N;;;;2176; 2167;ROMAN NUMERAL EIGHT;Nl;0;L; 0056 0049 0049 0049;;;8;N;;;;2177; 2168;ROMAN NUMERAL NINE;Nl;0;L; 0049 0058;;;9;N;;;;2178; 2169;ROMAN NUMERAL TEN;Nl;0;L; 0058;;;10;N;;;;2179; 216A;ROMAN NUMERAL ELEVEN;Nl;0;L; 0058 0049;;;11;N;;;;217A; 216B;ROMAN NUMERAL TWELVE;Nl;0;L; 0058 0049 0049;;;12;N;;;;217B; 216C;ROMAN NUMERAL FIFTY;Nl;0;L; 004C;;;50;N;;;;217C; 216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0043;;;100;N;;;;217D; 216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0044;;;500;N;;;;217E; 216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 004D;;;1000;N;;;;217F; 2170;SMALL ROMAN NUMERAL ONE;Nl;0;L; 0069;;;1;N;;;2160;;2160 2171;SMALL ROMAN NUMERAL TWO;Nl;0;L; 0069 0069;;;2;N;;;2161;;2161 2172;SMALL ROMAN NUMERAL THREE;Nl;0;L; 0069 0069 0069;;;3;N;;;2162;;2162 2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L; 0069 0076;;;4;N;;;2163;;2163 2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L; 0076;;;5;N;;;2164;;2164 2175;SMALL ROMAN NUMERAL SIX;Nl;0;L; 0076 0069;;;6;N;;;2165;;2165 2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L; 0076 0069 0069;;;7;N;;;2166;;2166 2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L; 0076 0069 0069 0069;;;8;N;;;2167;;2167 2178;SMALL ROMAN NUMERAL NINE;Nl;0;L; 0069 0078;;;9;N;;;2168;;2168 2179;SMALL ROMAN NUMERAL TEN;Nl;0;L; 0078;;;10;N;;;2169;;2169 217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L; 0078 0069;;;11;N;;;216A;;216A 217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L; 0078 0069 0069;;;12;N;;;216B;;216B 217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L; 006C;;;50;N;;;216C;;216C 217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0063;;;100;N;;;216D;;216D 217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0064;;;500;N;;;216E;;216E 217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 006D;;;1000;N;;;216F;;216F 2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; 2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; 2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; 2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184; 2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183 2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;; 2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;; 2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;; 2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;; 2189;VULGAR FRACTION ZERO THIRDS;No;0;ON; 0030 2044 0033;;;0;N;;;;; 2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; 2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; 2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; 2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; 2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; 2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; 2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; 2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; 2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; 219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; 219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; 219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; 219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; 219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; 219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; 21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; 21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; 21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; 21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; 21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; 21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; 21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; 21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; 21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; 21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; 21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; 21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; 21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; 21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; 21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; 21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; 21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; 21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; 21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; 21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; 21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; 21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; 21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; 21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; 21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; 21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; 21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; 21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; 21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; 21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; 21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; 21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; 21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; 21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; 21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; 21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; 21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; 21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; 21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; 21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; 21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; 21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; 21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; 21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; 21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; 21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; 21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; 21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; 21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; 21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; 21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; 21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; 21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; 21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; 21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; 21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; 21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; 21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; 21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; 21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; 21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; 21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; 21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; 21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; 21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; 21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; 21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; 21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; 21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; 21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; 21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; 21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; 21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 2200;FOR ALL;Sm;0;ON;;;;;N;;;;; 2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; 2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; 2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; 2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; 2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; 2206;INCREMENT;Sm;0;ON;;;;;N;;;;; 2207;NABLA;Sm;0;ON;;;;;N;;;;; 2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; 220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; 220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; 220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; 2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; 2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; 2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;; 2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; 2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; 2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; 2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; 2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; 221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; 221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; 221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; 221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; 221E;INFINITY;Sm;0;ON;;;;;N;;;;; 221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; 2220;ANGLE;Sm;0;ON;;;;;Y;;;;; 2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; 2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; 2223;DIVIDES;Sm;0;ON;;;;;N;;;;; 2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; 2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; 2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; 2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; 222A;UNION;Sm;0;ON;;;;;N;;;;; 222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222C;DOUBLE INTEGRAL;Sm;0;ON; 222B 222B;;;;Y;;;;; 222D;TRIPLE INTEGRAL;Sm;0;ON; 222B 222B 222B;;;;Y;;;;; 222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222F;SURFACE INTEGRAL;Sm;0;ON; 222E 222E;;;;Y;;;;; 2230;VOLUME INTEGRAL;Sm;0;ON; 222E 222E 222E;;;;Y;;;;; 2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2234;THEREFORE;Sm;0;ON;;;;;N;;;;; 2235;BECAUSE;Sm;0;ON;;;;;N;;;;; 2236;RATIO;Sm;0;ON;;;;;N;;;;; 2237;PROPORTION;Sm;0;ON;;;;;N;;;;; 2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; 2239;EXCESS;Sm;0;ON;;;;;Y;;;;; 223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; 223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; 223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;; 223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; 223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; 2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; 2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; 2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; 2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; 2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; 2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; 224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; 224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; 2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; 2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; 2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; 2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; 2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; 2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; 2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; 2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; 225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; 225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; 225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; 225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; 225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; 225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; 2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; 2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; 2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; 2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; 2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; 2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; 2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; 2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; 226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; 226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; 226C;BETWEEN;Sm;0;ON;;;;;N;;;;; 226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;; 226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; 226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; 2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; 2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; 2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; 2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; 2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; 2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; 2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; 2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; 2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; 2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; 227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; 227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; 2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; 2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; 2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; 2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; 2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; 2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; 2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; 228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; 228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; 228C;MULTISET;Sm;0;ON;;;;;Y;;;;; 228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; 228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; 228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; 2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; 2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; 2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; 2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; 229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; 229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; 229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; 229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; 22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; 22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; 22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; 22A5;UP TACK;Sm;0;ON;;;;;N;;;;; 22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; 22A7;MODELS;Sm;0;ON;;;;;Y;;;;; 22A8;TRUE;Sm;0;ON;;;;;Y;;;;; 22A9;FORCES;Sm;0;ON;;;;;Y;;;;; 22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; 22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; 22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; 22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; 22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; 22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; 22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; 22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; 22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; 22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; 22BB;XOR;Sm;0;ON;;;;;N;;;;; 22BC;NAND;Sm;0;ON;;;;;N;;;;; 22BD;NOR;Sm;0;ON;;;;;N;;;;; 22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; 22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; 22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; 22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; 22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; 22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; 22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; 22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; 22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; 22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; 22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; 22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; 22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; 22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; 22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; 22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; 22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; 22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; 22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; 22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; 22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; 22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; 22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; 22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; 22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; 22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; 22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; 22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; 22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; 22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; 22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; 22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; 22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; 22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; 22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; 2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; 2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; 2302;HOUSE;So;0;ON;;;;;N;;;;; 2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; 2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; 2305;PROJECTIVE;So;0;ON;;;;;N;;;;; 2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; 2307;WAVY LINE;So;0;ON;;;;;N;;;;; 2308;LEFT CEILING;Ps;0;ON;;;;;Y;;;;; 2309;RIGHT CEILING;Pe;0;ON;;;;;Y;;;;; 230A;LEFT FLOOR;Ps;0;ON;;;;;Y;;;;; 230B;RIGHT FLOOR;Pe;0;ON;;;;;Y;;;;; 230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; 230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; 230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; 230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; 2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; 2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; 2312;ARC;So;0;ON;;;;;N;;;;; 2313;SEGMENT;So;0;ON;;;;;N;;;;; 2314;SECTOR;So;0;ON;;;;;N;;;;; 2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; 2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; 2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; 2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; 231A;WATCH;So;0;ON;;;;;N;;;;; 231B;HOURGLASS;So;0;ON;;;;;N;;;;; 231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; 231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; 231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; 231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; 2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2322;FROWN;So;0;ON;;;;;N;;;;; 2323;SMILE;So;0;ON;;;;;N;;;;; 2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; 2325;OPTION KEY;So;0;ON;;;;;N;;;;; 2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; 2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; 2328;KEYBOARD;So;0;ON;;;;;N;;;;; 2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; 232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; 232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; 232C;BENZENE RING;So;0;ON;;;;;N;;;;; 232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; 232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; 232F;SYMMETRY;So;0;ON;;;;;N;;;;; 2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; 2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; 2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; 2333;SLOPE;So;0;ON;;;;;N;;;;; 2334;COUNTERBORE;So;0;ON;;;;;N;;;;; 2335;COUNTERSINK;So;0;ON;;;;;N;;;;; 2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; 2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; 2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; 2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; 233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; 233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; 233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; 233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; 233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; 233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; 2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; 2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; 2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; 2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; 2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; 2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; 2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; 2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; 2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; 2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; 234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;; 234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; 234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; 234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; 234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;; 234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; 2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; 2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;; 2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; 2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; 2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; 2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;; 2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; 2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; 2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; 2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; 235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; 235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; 235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; 235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; 235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; 235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; 2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; 2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;; 2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; 2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; 2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; 2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; 2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; 2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; 2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; 2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; 236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; 236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; 236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; 236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; 236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; 236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; 2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; 2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; 2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; 2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; 2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; 2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; 2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; 2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; 2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; 2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; 237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; 237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; 237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; 237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; 237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; 237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; 2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; 2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; 2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; 2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; 2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; 2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; 2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;; 238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;; 238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;; 238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; 238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; 238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; 238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; 2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; 2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; 2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; 2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; 2398;NEXT PAGE;So;0;ON;;;;;N;;;;; 2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; 23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; 23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; 23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; 23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; 23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; 23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; 23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; 23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; 23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; 23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; 23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; 23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; 23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; 23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; 23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; 23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;; 23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;; 23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;; 23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;; 23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;; 23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;; 23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;; 23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;; 23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;; 23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;; 23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;; 23DA;EARTH GROUND;So;0;ON;;;;;N;;;;; 23DB;FUSE;So;0;ON;;;;;N;;;;; 23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;; 23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;; 23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;; 23E5;FLATNESS;So;0;ON;;;;;N;;;;; 23E6;AC CURRENT;So;0;ON;;;;;N;;;;; 23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; 23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; 23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; 23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;; 23F1;STOPWATCH;So;0;ON;;;;;N;;;;; 23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;; 23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;; 23F4;BLACK MEDIUM LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F5;BLACK MEDIUM RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F6;BLACK MEDIUM UP-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F7;BLACK MEDIUM DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F8;DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; 23F9;BLACK SQUARE FOR STOP;So;0;ON;;;;;N;;;;; 23FA;BLACK CIRCLE FOR RECORD;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; 2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; 2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; 2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; 2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; 2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; 2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; 2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; 240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; 240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; 240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; 240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; 240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; 240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; 2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; 2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; 2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; 2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; 2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; 2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; 2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; 2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; 2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; 2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; 241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; 241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; 241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; 241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; 241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; 241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; 2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; 2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; 2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; 2423;OPEN BOX;So;0;ON;;;;;N;;;;; 2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; 2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; 2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; 2440;OCR HOOK;So;0;ON;;;;;N;;;;; 2441;OCR CHAIR;So;0;ON;;;;;N;;;;; 2442;OCR FORK;So;0;ON;;;;;N;;;;; 2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; 2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; 2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; 2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; 2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; 2448;OCR DASH;So;0;ON;;;;;N;;;;; 2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; 244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; 2460;CIRCLED DIGIT ONE;No;0;ON; 0031;;1;1;N;;;;; 2461;CIRCLED DIGIT TWO;No;0;ON; 0032;;2;2;N;;;;; 2462;CIRCLED DIGIT THREE;No;0;ON; 0033;;3;3;N;;;;; 2463;CIRCLED DIGIT FOUR;No;0;ON; 0034;;4;4;N;;;;; 2464;CIRCLED DIGIT FIVE;No;0;ON; 0035;;5;5;N;;;;; 2465;CIRCLED DIGIT SIX;No;0;ON; 0036;;6;6;N;;;;; 2466;CIRCLED DIGIT SEVEN;No;0;ON; 0037;;7;7;N;;;;; 2467;CIRCLED DIGIT EIGHT;No;0;ON; 0038;;8;8;N;;;;; 2468;CIRCLED DIGIT NINE;No;0;ON; 0039;;9;9;N;;;;; 2469;CIRCLED NUMBER TEN;No;0;ON; 0031 0030;;;10;N;;;;; 246A;CIRCLED NUMBER ELEVEN;No;0;ON; 0031 0031;;;11;N;;;;; 246B;CIRCLED NUMBER TWELVE;No;0;ON; 0031 0032;;;12;N;;;;; 246C;CIRCLED NUMBER THIRTEEN;No;0;ON; 0031 0033;;;13;N;;;;; 246D;CIRCLED NUMBER FOURTEEN;No;0;ON; 0031 0034;;;14;N;;;;; 246E;CIRCLED NUMBER FIFTEEN;No;0;ON; 0031 0035;;;15;N;;;;; 246F;CIRCLED NUMBER SIXTEEN;No;0;ON; 0031 0036;;;16;N;;;;; 2470;CIRCLED NUMBER SEVENTEEN;No;0;ON; 0031 0037;;;17;N;;;;; 2471;CIRCLED NUMBER EIGHTEEN;No;0;ON; 0031 0038;;;18;N;;;;; 2472;CIRCLED NUMBER NINETEEN;No;0;ON; 0031 0039;;;19;N;;;;; 2473;CIRCLED NUMBER TWENTY;No;0;ON; 0032 0030;;;20;N;;;;; 2474;PARENTHESIZED DIGIT ONE;No;0;ON; 0028 0031 0029;;1;1;N;;;;; 2475;PARENTHESIZED DIGIT TWO;No;0;ON; 0028 0032 0029;;2;2;N;;;;; 2476;PARENTHESIZED DIGIT THREE;No;0;ON; 0028 0033 0029;;3;3;N;;;;; 2477;PARENTHESIZED DIGIT FOUR;No;0;ON; 0028 0034 0029;;4;4;N;;;;; 2478;PARENTHESIZED DIGIT FIVE;No;0;ON; 0028 0035 0029;;5;5;N;;;;; 2479;PARENTHESIZED DIGIT SIX;No;0;ON; 0028 0036 0029;;6;6;N;;;;; 247A;PARENTHESIZED DIGIT SEVEN;No;0;ON; 0028 0037 0029;;7;7;N;;;;; 247B;PARENTHESIZED DIGIT EIGHT;No;0;ON; 0028 0038 0029;;8;8;N;;;;; 247C;PARENTHESIZED DIGIT NINE;No;0;ON; 0028 0039 0029;;9;9;N;;;;; 247D;PARENTHESIZED NUMBER TEN;No;0;ON; 0028 0031 0030 0029;;;10;N;;;;; 247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON; 0028 0031 0031 0029;;;11;N;;;;; 247F;PARENTHESIZED NUMBER TWELVE;No;0;ON; 0028 0031 0032 0029;;;12;N;;;;; 2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON; 0028 0031 0033 0029;;;13;N;;;;; 2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON; 0028 0031 0034 0029;;;14;N;;;;; 2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON; 0028 0031 0035 0029;;;15;N;;;;; 2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON; 0028 0031 0036 0029;;;16;N;;;;; 2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON; 0028 0031 0037 0029;;;17;N;;;;; 2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON; 0028 0031 0038 0029;;;18;N;;;;; 2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON; 0028 0031 0039 0029;;;19;N;;;;; 2487;PARENTHESIZED NUMBER TWENTY;No;0;ON; 0028 0032 0030 0029;;;20;N;;;;; 2488;DIGIT ONE FULL STOP;No;0;EN; 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; 2489;DIGIT TWO FULL STOP;No;0;EN; 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; 248A;DIGIT THREE FULL STOP;No;0;EN; 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; 248B;DIGIT FOUR FULL STOP;No;0;EN; 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; 248C;DIGIT FIVE FULL STOP;No;0;EN; 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; 248D;DIGIT SIX FULL STOP;No;0;EN; 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; 248E;DIGIT SEVEN FULL STOP;No;0;EN; 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; 248F;DIGIT EIGHT FULL STOP;No;0;EN; 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; 2490;DIGIT NINE FULL STOP;No;0;EN; 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; 2491;NUMBER TEN FULL STOP;No;0;EN; 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; 2492;NUMBER ELEVEN FULL STOP;No;0;EN; 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; 2493;NUMBER TWELVE FULL STOP;No;0;EN; 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; 2494;NUMBER THIRTEEN FULL STOP;No;0;EN; 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; 2495;NUMBER FOURTEEN FULL STOP;No;0;EN; 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; 2496;NUMBER FIFTEEN FULL STOP;No;0;EN; 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; 2497;NUMBER SIXTEEN FULL STOP;No;0;EN; 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; 2498;NUMBER SEVENTEEN FULL STOP;No;0;EN; 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; 2499;NUMBER EIGHTEEN FULL STOP;No;0;EN; 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; 249A;NUMBER NINETEEN FULL STOP;No;0;EN; 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; 249B;NUMBER TWENTY FULL STOP;No;0;EN; 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; 249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L; 0028 0061 0029;;;;N;;;;; 249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L; 0028 0062 0029;;;;N;;;;; 249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L; 0028 0063 0029;;;;N;;;;; 249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L; 0028 0064 0029;;;;N;;;;; 24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L; 0028 0065 0029;;;;N;;;;; 24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L; 0028 0066 0029;;;;N;;;;; 24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L; 0028 0067 0029;;;;N;;;;; 24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L; 0028 0068 0029;;;;N;;;;; 24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L; 0028 0069 0029;;;;N;;;;; 24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L; 0028 006A 0029;;;;N;;;;; 24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L; 0028 006B 0029;;;;N;;;;; 24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L; 0028 006C 0029;;;;N;;;;; 24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L; 0028 006D 0029;;;;N;;;;; 24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L; 0028 006E 0029;;;;N;;;;; 24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L; 0028 006F 0029;;;;N;;;;; 24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L; 0028 0070 0029;;;;N;;;;; 24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L; 0028 0071 0029;;;;N;;;;; 24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L; 0028 0072 0029;;;;N;;;;; 24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L; 0028 0073 0029;;;;N;;;;; 24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L; 0028 0074 0029;;;;N;;;;; 24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L; 0028 0075 0029;;;;N;;;;; 24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L; 0028 0076 0029;;;;N;;;;; 24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L; 0028 0077 0029;;;;N;;;;; 24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L; 0028 0078 0029;;;;N;;;;; 24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L; 0028 0079 0029;;;;N;;;;; 24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L; 0028 007A 0029;;;;N;;;;; 24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;24D0; 24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;24D1; 24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;24D2; 24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;24D3; 24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;24D4; 24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;24D5; 24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;24D6; 24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;24D7; 24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;24D8; 24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;24D9; 24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;24DA; 24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;24DB; 24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;24DC; 24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;24DD; 24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;24DE; 24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;24DF; 24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;24E0; 24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;24E1; 24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;24E2; 24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;24E3; 24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;24E4; 24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;24E5; 24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;24E6; 24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;24E7; 24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;24E8; 24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;24E9; 24D0;CIRCLED LATIN SMALL LETTER A;So;0;L; 0061;;;;N;;;24B6;;24B6 24D1;CIRCLED LATIN SMALL LETTER B;So;0;L; 0062;;;;N;;;24B7;;24B7 24D2;CIRCLED LATIN SMALL LETTER C;So;0;L; 0063;;;;N;;;24B8;;24B8 24D3;CIRCLED LATIN SMALL LETTER D;So;0;L; 0064;;;;N;;;24B9;;24B9 24D4;CIRCLED LATIN SMALL LETTER E;So;0;L; 0065;;;;N;;;24BA;;24BA 24D5;CIRCLED LATIN SMALL LETTER F;So;0;L; 0066;;;;N;;;24BB;;24BB 24D6;CIRCLED LATIN SMALL LETTER G;So;0;L; 0067;;;;N;;;24BC;;24BC 24D7;CIRCLED LATIN SMALL LETTER H;So;0;L; 0068;;;;N;;;24BD;;24BD 24D8;CIRCLED LATIN SMALL LETTER I;So;0;L; 0069;;;;N;;;24BE;;24BE 24D9;CIRCLED LATIN SMALL LETTER J;So;0;L; 006A;;;;N;;;24BF;;24BF 24DA;CIRCLED LATIN SMALL LETTER K;So;0;L; 006B;;;;N;;;24C0;;24C0 24DB;CIRCLED LATIN SMALL LETTER L;So;0;L; 006C;;;;N;;;24C1;;24C1 24DC;CIRCLED LATIN SMALL LETTER M;So;0;L; 006D;;;;N;;;24C2;;24C2 24DD;CIRCLED LATIN SMALL LETTER N;So;0;L; 006E;;;;N;;;24C3;;24C3 24DE;CIRCLED LATIN SMALL LETTER O;So;0;L; 006F;;;;N;;;24C4;;24C4 24DF;CIRCLED LATIN SMALL LETTER P;So;0;L; 0070;;;;N;;;24C5;;24C5 24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L; 0071;;;;N;;;24C6;;24C6 24E1;CIRCLED LATIN SMALL LETTER R;So;0;L; 0072;;;;N;;;24C7;;24C7 24E2;CIRCLED LATIN SMALL LETTER S;So;0;L; 0073;;;;N;;;24C8;;24C8 24E3;CIRCLED LATIN SMALL LETTER T;So;0;L; 0074;;;;N;;;24C9;;24C9 24E4;CIRCLED LATIN SMALL LETTER U;So;0;L; 0075;;;;N;;;24CA;;24CA 24E5;CIRCLED LATIN SMALL LETTER V;So;0;L; 0076;;;;N;;;24CB;;24CB 24E6;CIRCLED LATIN SMALL LETTER W;So;0;L; 0077;;;;N;;;24CC;;24CC 24E7;CIRCLED LATIN SMALL LETTER X;So;0;L; 0078;;;;N;;;24CD;;24CD 24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L; 0079;;;;N;;;24CE;;24CE 24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L; 007A;;;;N;;;24CF;;24CF 24EA;CIRCLED DIGIT ZERO;No;0;ON; 0030;;0;0;N;;;;; 24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; 24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; 24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; 24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; 24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; 24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; 24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; 24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; 24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; 24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; 24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; 24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; 24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; 24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; 24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; 24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; 24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; 24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; 24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; 24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;; 2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; 2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; 2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; 2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; 2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; 2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; 2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; 2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; 2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; 2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; 250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; 250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; 250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; 250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; 250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; 250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; 2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; 2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; 2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; 2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; 2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; 2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; 2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; 2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; 2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; 2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; 251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; 251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; 251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; 251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; 251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; 251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; 2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; 2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; 2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; 2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; 2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; 2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; 2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; 2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; 2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; 2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; 252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; 252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; 252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; 252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; 252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; 252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; 2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; 2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; 2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; 2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; 2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; 2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; 2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; 2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; 2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; 2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; 253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; 253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; 253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; 253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; 253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; 253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; 2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; 2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; 2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; 2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; 2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; 2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; 2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; 2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; 2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; 2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; 254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; 254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; 254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; 254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; 254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; 254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; 2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; 2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; 2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; 2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; 2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; 2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; 2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; 2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; 2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; 2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; 255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; 255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; 255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; 255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; 255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; 255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; 2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; 2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; 2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; 2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; 2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; 2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; 2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; 2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; 2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; 2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; 256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; 256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; 256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; 256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; 256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; 256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; 2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; 2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; 2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; 2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; 2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; 2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; 2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; 2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; 2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; 2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; 257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; 257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; 257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; 257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; 257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; 257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; 2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; 2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; 2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; 2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2588;FULL BLOCK;So;0;ON;;;;;N;;;;; 2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; 258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; 258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; 2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; 2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; 2593;DARK SHADE;So;0;ON;;;;;N;;;;; 2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; 2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; 2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; 2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; 259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; 25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; 25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; 25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; 25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; 25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; 25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; 25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; 25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; 25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; 25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; 25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; 25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; 25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; 25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; 25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; 25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; 25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; 25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; 25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; 25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; 25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; 25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; 25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; 25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; 25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; 25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; 25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; 25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 25C9;FISHEYE;So;0;ON;;;;;N;;;;; 25CA;LOZENGE;So;0;ON;;;;;N;;;;; 25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; 25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25CE;BULLSEYE;So;0;ON;;;;;N;;;;; 25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; 25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; 25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; 25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; 25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; 25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; 25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; 25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; 25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; 25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; 2601;CLOUD;So;0;ON;;;;;N;;;;; 2602;UMBRELLA;So;0;ON;;;;;N;;;;; 2603;SNOWMAN;So;0;ON;;;;;N;;;;; 2604;COMET;So;0;ON;;;;;N;;;;; 2605;BLACK STAR;So;0;ON;;;;;N;;;;; 2606;WHITE STAR;So;0;ON;;;;;N;;;;; 2607;LIGHTNING;So;0;ON;;;;;N;;;;; 2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; 2609;SUN;So;0;ON;;;;;N;;;;; 260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; 260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; 260C;CONJUNCTION;So;0;ON;;;;;N;;;;; 260D;OPPOSITION;So;0;ON;;;;;N;;;;; 260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; 260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; 2610;BALLOT BOX;So;0;ON;;;;;N;;;;; 2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; 2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; 2613;SALTIRE;So;0;ON;;;;;N;;;;; 2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;; 2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;; 2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 2618;SHAMROCK;So;0;ON;;;;;N;;;;; 2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; 2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; 2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; 2624;CADUCEUS;So;0;ON;;;;;N;;;;; 2625;ANKH;So;0;ON;;;;;N;;;;; 2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; 2627;CHI RHO;So;0;ON;;;;;N;;;;; 2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; 2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; 262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; 262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; 262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; 262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; 262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; 262F;YIN YANG;So;0;ON;;;;;N;;;;; 2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; 2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; 2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; 2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; 2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; 2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; 2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; 2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; 2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; 263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; 263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; 263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; 263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; 263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; 263F;MERCURY;So;0;ON;;;;;N;;;;; 2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; 2641;EARTH;So;0;ON;;;;;N;;;;; 2642;MALE SIGN;So;0;ON;;;;;N;;;;; 2643;JUPITER;So;0;ON;;;;;N;;;;; 2644;SATURN;So;0;ON;;;;;N;;;;; 2645;URANUS;So;0;ON;;;;;N;;;;; 2646;NEPTUNE;So;0;ON;;;;;N;;;;; 2647;PLUTO;So;0;ON;;;;;N;;;;; 2648;ARIES;So;0;ON;;;;;N;;;;; 2649;TAURUS;So;0;ON;;;;;N;;;;; 264A;GEMINI;So;0;ON;;;;;N;;;;; 264B;CANCER;So;0;ON;;;;;N;;;;; 264C;LEO;So;0;ON;;;;;N;;;;; 264D;VIRGO;So;0;ON;;;;;N;;;;; 264E;LIBRA;So;0;ON;;;;;N;;;;; 264F;SCORPIUS;So;0;ON;;;;;N;;;;; 2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; 2651;CAPRICORN;So;0;ON;;;;;N;;;;; 2652;AQUARIUS;So;0;ON;;;;;N;;;;; 2653;PISCES;So;0;ON;;;;;N;;;;; 2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; 2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; 2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; 2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; 2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; 2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; 265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; 265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; 265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; 265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; 265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; 265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; 2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; 2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; 2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; 2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; 2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; 2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; 2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; 2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; 266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; 266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; 266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; 266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; 266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; 266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; 2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;; 2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;; 2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;; 2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;; 2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;; 2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;; 2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;; 267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; 267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;; 267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;; 2680;DIE FACE-1;So;0;ON;;;;;N;;;;; 2681;DIE FACE-2;So;0;ON;;;;;N;;;;; 2682;DIE FACE-3;So;0;ON;;;;;N;;;;; 2683;DIE FACE-4;So;0;ON;;;;;N;;;;; 2684;DIE FACE-5;So;0;ON;;;;;N;;;;; 2685;DIE FACE-6;So;0;ON;;;;;N;;;;; 2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; 2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; 2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; 2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; 268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;; 268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;; 268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;; 268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;; 268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;; 268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;; 2690;WHITE FLAG;So;0;ON;;;;;N;;;;; 2691;BLACK FLAG;So;0;ON;;;;;N;;;;; 2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;; 2693;ANCHOR;So;0;ON;;;;;N;;;;; 2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;; 2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;; 2696;SCALES;So;0;ON;;;;;N;;;;; 2697;ALEMBIC;So;0;ON;;;;;N;;;;; 2698;FLOWER;So;0;ON;;;;;N;;;;; 2699;GEAR;So;0;ON;;;;;N;;;;; 269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;; 269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;; 269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;; 269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;; 269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;; 26A0;WARNING SIGN;So;0;ON;;;;;N;;;;; 26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;; 26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;; 26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;; 26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;; 26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;; 26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;; 26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;; 26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;; 26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;; 26B0;COFFIN;So;0;ON;;;;;N;;;;; 26B1;FUNERAL URN;So;0;ON;;;;;N;;;;; 26B2;NEUTER;So;0;ON;;;;;N;;;;; 26B3;CERES;So;0;ON;;;;;N;;;;; 26B4;PALLAS;So;0;ON;;;;;N;;;;; 26B5;JUNO;So;0;ON;;;;;N;;;;; 26B6;VESTA;So;0;ON;;;;;N;;;;; 26B7;CHIRON;So;0;ON;;;;;N;;;;; 26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;; 26B9;SEXTILE;So;0;ON;;;;;N;;;;; 26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;; 26BB;QUINCUNX;So;0;ON;;;;;N;;;;; 26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;; 26BD;SOCCER BALL;So;0;ON;;;;;N;;;;; 26BE;BASEBALL;So;0;ON;;;;;N;;;;; 26BF;SQUARED KEY;So;0;ON;;;;;N;;;;; 26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;; 26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; 26C6;RAIN;So;0;ON;;;;;N;;;;; 26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;; 26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;; 26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; 26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; 26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; 26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;; 26CF;PICK;So;0;ON;;;;;N;;;;; 26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; 26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; 26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;; 26D3;CHAINS;So;0;ON;;;;;N;;;;; 26D4;NO ENTRY;So;0;ON;;;;;N;;;;; 26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;; 26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;; 26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;; 26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; 26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; 26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; 26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;; 26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; 26E4;PENTAGRAM;So;0;ON;;;;;N;;;;; 26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; 26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; 26EA;CHURCH;So;0;ON;;;;;N;;;;; 26EB;CASTLE;So;0;ON;;;;;N;;;;; 26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;; 26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;; 26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;; 26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;; 26F0;MOUNTAIN;So;0;ON;;;;;N;;;;; 26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;; 26F2;FOUNTAIN;So;0;ON;;;;;N;;;;; 26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;; 26F4;FERRY;So;0;ON;;;;;N;;;;; 26F5;SAILBOAT;So;0;ON;;;;;N;;;;; 26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;; 26F7;SKIER;So;0;ON;;;;;N;;;;; 26F8;ICE SKATE;So;0;ON;;;;;N;;;;; 26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;; 26FA;TENT;So;0;ON;;;;;N;;;;; 26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;; 26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;; 26FD;FUEL PUMP;So;0;ON;;;;;N;;;;; 26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;; 26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;; 2700;BLACK SAFETY SCISSORS;So;0;ON;;;;;N;;;;; 2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; 2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; 2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; 2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; 2708;AIRPLANE;So;0;ON;;;;;N;;;;; 2709;ENVELOPE;So;0;ON;;;;;N;;;;; 270A;RAISED FIST;So;0;ON;;;;;N;;;;; 270B;RAISED HAND;So;0;ON;;;;;N;;;;; 270C;VICTORY HAND;So;0;ON;;;;;N;;;;; 270D;WRITING HAND;So;0;ON;;;;;N;;;;; 270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 270F;PENCIL;So;0;ON;;;;;N;;;;; 2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 2711;WHITE NIB;So;0;ON;;;;;N;;;;; 2712;BLACK NIB;So;0;ON;;;;;N;;;;; 2713;CHECK MARK;So;0;ON;;;;;N;;;;; 2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2717;BALLOT X;So;0;ON;;;;;N;;;;; 2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; 2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; 271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; 271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; 271D;LATIN CROSS;So;0;ON;;;;;N;;;;; 271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; 2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; 2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; 2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2728;SPARKLES;So;0;ON;;;;;N;;;;; 2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; 272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; 272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; 272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; 2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; 2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; 2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; 273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; 273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; 273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; 2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; 2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; 2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; 2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; 2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; 2747;SPARKLE;So;0;ON;;;;;N;;;;; 2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; 2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274C;CROSS MARK;So;0;ON;;;;;N;;;;; 274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;; 274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; 2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; 2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; 2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; 275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; 275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; 2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; 2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; 2766;FLORAL HEART;So;0;ON;;;;;N;;;;; 2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; 2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; 2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; 2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; 277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; 277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; 277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; 277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; 277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; 277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; 2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; 2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; 2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; 2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; 2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; 2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; 2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; 2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; 278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; 278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; 278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; 278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; 278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; 278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; 2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; 2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; 2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; 2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;; 2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;; 2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;; 2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; 2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; 279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; 279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; 279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; 279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; 279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; 279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; 27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; 27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; 27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; 27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; 27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; 27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; 27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; 27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; 27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; 27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B0;CURLY LOOP;So;0;ON;;;;;N;;;;; 27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; 27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; 27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; 27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; 27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; 27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; 27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; 27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; 27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; 27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;; 27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; 27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; 27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;; 27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;; 27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;; 27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;; 27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;; 27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;; 27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; 27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 27CB;MATHEMATICAL RISING DIAGONAL;Sm;0;ON;;;;;Y;;;;; 27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; 27CD;MATHEMATICAL FALLING DIAGONAL;Sm;0;ON;;;;;Y;;;;; 27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;; 27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;; 27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; 27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; 27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; 27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; 27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; 27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; 27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; 27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; 27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; 27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; 27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; 27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; 27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; 27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;; 2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;; 2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;; 2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;; 2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;; 2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;; 2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;; 2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;; 2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;; 2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;; 280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;; 280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;; 280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;; 280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;; 280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;; 280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;; 2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;; 2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;; 2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;; 2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;; 2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;; 2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;; 2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;; 2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;; 2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;; 2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;; 281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;; 281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;; 281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;; 281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;; 281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;; 281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;; 2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;; 2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;; 2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;; 2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;; 2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;; 2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;; 2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;; 2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;; 2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;; 2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;; 282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;; 282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;; 282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;; 282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;; 282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;; 282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;; 2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;; 2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;; 2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;; 2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;; 2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;; 2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;; 2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;; 2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;; 2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;; 2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;; 283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;; 283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;; 283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;; 283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;; 283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;; 283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;; 2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;; 2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;; 2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;; 2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;; 2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;; 2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;; 2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;; 2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;; 2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;; 2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;; 284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;; 284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;; 284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;; 284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;; 284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;; 284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;; 2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;; 2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;; 2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;; 2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;; 2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;; 2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;; 2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;; 2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;; 2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;; 2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;; 285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;; 285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;; 285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;; 285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;; 285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;; 285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;; 2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;; 2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;; 2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;; 2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;; 2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;; 2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;; 2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;; 2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;; 2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;; 2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;; 286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;; 286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;; 286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;; 286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;; 286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;; 286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;; 2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;; 2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;; 2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;; 2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;; 2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;; 2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;; 2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;; 2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;; 2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;; 2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;; 287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;; 287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;; 287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;; 287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;; 287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;; 287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;; 2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;; 2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;; 2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;; 2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;; 2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;; 2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;; 2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;; 2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;; 2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;; 2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;; 288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;; 288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;; 288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;; 288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;; 288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;; 288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;; 2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;; 2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;; 2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;; 2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;; 2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;; 2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;; 2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;; 2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;; 2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;; 2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;; 289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;; 289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;; 289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;; 289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;; 289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;; 289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;; 28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;; 28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;; 28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;; 28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;; 28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;; 28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;; 28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;; 28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;; 28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;; 28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;; 28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;; 28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;; 28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;; 28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;; 28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;; 28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;; 28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;; 28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;; 28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;; 28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;; 28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;; 28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;; 28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;; 28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;; 28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;; 28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;; 28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;; 28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;; 28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;; 28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;; 28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;; 28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;; 28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;; 28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;; 28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;; 28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;; 28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;; 28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;; 28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;; 28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;; 28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;; 28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;; 28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;; 28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;; 28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;; 28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;; 28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;; 28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;; 28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;; 28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;; 28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;; 28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;; 28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;; 28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;; 28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;; 28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;; 28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;; 28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;; 28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;; 28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;; 28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;; 28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;; 28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;; 28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;; 28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;; 28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;; 28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;; 28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;; 28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;; 28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;; 28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;; 28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;; 28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;; 28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;; 28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;; 28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;; 28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;; 28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;; 28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;; 28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;; 28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;; 28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;; 28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;; 28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;; 28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;; 28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;; 28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;; 28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;; 28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;; 28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;; 28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;; 28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;; 28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;; 28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;; 28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;; 28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;; 2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; 2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; 2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; 2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; 2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; 293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; 293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; 2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; 2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; 297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; 297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; 2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; 2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; 2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; 2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; 2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; 2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; 2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; 2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; 298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; 298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; 298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; 298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; 298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; 298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; 2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; 2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; 2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; 2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; 299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; 299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; 299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; 299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; 299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; 29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; 29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; 29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; 29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; 29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; 29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; 29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; 29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; 29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; 29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; 29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; 29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; 29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; 29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; 29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; 29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; 29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; 29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; 29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; 29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; 29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; 29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; 29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; 29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; 29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; 29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; 29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; 29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; 29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; 29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; 29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; 29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; 29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; 29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 29FE;TINY;Sm;0;ON;;;;;N;;;;; 29FF;MINY;Sm;0;ON;;;;;N;;;;; 2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; 2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; 2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; 2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; 2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; 2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; 2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON; 222B 222B 222B 222B;;;;Y;;;;; 2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; 2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; 2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; 2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; 2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; 2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; 2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; 2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; 2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; 2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2A1D;JOIN;Sm;0;ON;;;;;N;;;;; 2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; 2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; 2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; 2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; 2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; 2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; 2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; 2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; 2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; 2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; 2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; 2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; 2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; 2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; 2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; 2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; 2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; 2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; 2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; 2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; 2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A74;DOUBLE COLON EQUAL;Sm;0;ON; 003A 003A 003D;;;;Y;;;;; 2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D;;;;N;;;;; 2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D 003D;;;;N;;;;; 2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; 2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; 2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; 2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; 2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; 2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; 2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; 2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; 2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; 2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; 2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; 2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; 2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;; 2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;; 2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; 2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; 2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; 2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; 2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; 2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; 2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; 2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; 2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; 2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; 2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;; 2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;; 2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;; 2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;; 2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;; 2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;; 2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;; 2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;; 2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B4D;DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW;So;0;ON;;;;;N;;;;; 2B4E;SHORT SLANTED NORTH ARROW;So;0;ON;;;;;N;;;;; 2B4F;SHORT BACKSLANTED SOUTH ARROW;So;0;ON;;;;;N;;;;; 2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;; 2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;; 2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;; 2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;; 2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;; 2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;; 2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;; 2B5A;SLANTED NORTH ARROW WITH HOOKED HEAD;So;0;ON;;;;;N;;;;; 2B5B;BACKSLANTED SOUTH ARROW WITH HOOKED TAIL;So;0;ON;;;;;N;;;;; 2B5C;SLANTED NORTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; 2B5D;BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; 2B5E;BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; 2B5F;SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; 2B60;LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B61;UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B62;RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B63;DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B64;LEFT RIGHT TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B65;UP DOWN TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B66;NORTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B67;NORTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B68;SOUTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B69;SOUTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B6A;LEFTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6B;UPWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6C;RIGHTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6D;DOWNWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6E;CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 2B6F;ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 2B70;LEFTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B71;UPWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B72;RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B73;DOWNWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B76;NORTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B77;NORTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B78;SOUTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B79;SOUTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B7A;LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7B;UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7C;RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7D;DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7E;HORIZONTAL TAB KEY;So;0;ON;;;;;N;;;;; 2B7F;VERTICAL TAB KEY;So;0;ON;;;;;N;;;;; 2B80;LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B81;UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B82;RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B83;DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B84;LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B85;UPWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B86;RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B87;DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B88;LEFTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B89;UPWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8A;RIGHTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8B;DOWNWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8C;ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8D;ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8E;ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8F;ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B90;RETURN LEFT;So;0;ON;;;;;N;;;;; 2B91;RETURN RIGHT;So;0;ON;;;;;N;;;;; 2B92;NEWLINE LEFT;So;0;ON;;;;;N;;;;; 2B93;NEWLINE RIGHT;So;0;ON;;;;;N;;;;; 2B94;FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE;So;0;ON;;;;;N;;;;; 2B95;RIGHTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B98;THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B99;THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9A;THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9B;THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9C;BLACK LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9D;BLACK UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9E;BLACK RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9F;BLACK DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2BA0;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; 2BA1;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; 2BA2;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; 2BA3;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; 2BA4;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; 2BA5;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; 2BA6;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2BA7;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2BA8;BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BA9;BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAA;BLACK CURVED UPWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAB;BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAC;BLACK CURVED LEFTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAD;BLACK CURVED RIGHTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAE;BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAF;BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; 2BB0;RIBBON ARROW DOWN LEFT;So;0;ON;;;;;N;;;;; 2BB1;RIBBON ARROW DOWN RIGHT;So;0;ON;;;;;N;;;;; 2BB2;RIBBON ARROW UP LEFT;So;0;ON;;;;;N;;;;; 2BB3;RIBBON ARROW UP RIGHT;So;0;ON;;;;;N;;;;; 2BB4;RIBBON ARROW LEFT UP;So;0;ON;;;;;N;;;;; 2BB5;RIBBON ARROW RIGHT UP;So;0;ON;;;;;N;;;;; 2BB6;RIBBON ARROW LEFT DOWN;So;0;ON;;;;;N;;;;; 2BB7;RIBBON ARROW RIGHT DOWN;So;0;ON;;;;;N;;;;; 2BB8;UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 2BB9;UP ARROWHEAD IN A RECTANGLE BOX;So;0;ON;;;;;N;;;;; 2BBD;BALLOT BOX WITH LIGHT X;So;0;ON;;;;;N;;;;; 2BBE;CIRCLED X;So;0;ON;;;;;N;;;;; 2BBF;CIRCLED BOLD X;So;0;ON;;;;;N;;;;; 2BC0;BLACK SQUARE CENTRED;So;0;ON;;;;;N;;;;; 2BC1;BLACK DIAMOND CENTRED;So;0;ON;;;;;N;;;;; 2BC2;TURNED BLACK PENTAGON;So;0;ON;;;;;N;;;;; 2BC3;HORIZONTAL BLACK OCTAGON;So;0;ON;;;;;N;;;;; 2BC4;BLACK OCTAGON;So;0;ON;;;;;N;;;;; 2BC5;BLACK MEDIUM UP-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC6;BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC7;BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC8;BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BCA;TOP HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 2BCB;BOTTOM HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 2BCC;LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; 2BCD;ROTATED LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; 2BCE;WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; 2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30; 2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31; 2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32; 2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33; 2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34; 2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35; 2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36; 2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37; 2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38; 2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39; 2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A; 2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B; 2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C; 2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D; 2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E; 2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F; 2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40; 2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41; 2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42; 2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43; 2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44; 2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45; 2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46; 2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47; 2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48; 2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49; 2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A; 2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B; 2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C; 2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D; 2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E; 2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F; 2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50; 2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51; 2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52; 2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53; 2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54; 2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55; 2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56; 2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57; 2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58; 2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59; 2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A; 2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B; 2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; 2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; 2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; 2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03 2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04 2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05 2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06 2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07 2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08 2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09 2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A 2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B 2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C 2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D 2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E 2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F 2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10 2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11 2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12 2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13 2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14 2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15 2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16 2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17 2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18 2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19 2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A 2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B 2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C 2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D 2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E 2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F 2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20 2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21 2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22 2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23 2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24 2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25 2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26 2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27 2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28 2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29 2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A 2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B 2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C 2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D 2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E 2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; 2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; 2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D; 2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D; 2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A 2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E 2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68; 2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67 2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A; 2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69 2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C; 2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B 2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251; 2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271; 2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250; 2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252; 2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;; 2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73; 2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72 2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;; 2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76; 2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75 2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;; 2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;; 2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;; 2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;; 2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;; 2C7C;LATIN SUBSCRIPT SMALL LETTER J;Lm;0;L; 006A;;;;N;;;;; 2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L; 0056;;;;N;;;;; 2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F; 2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240; 2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81; 2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80 2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83; 2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82 2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85; 2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84 2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87; 2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86 2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89; 2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88 2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B; 2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A 2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D; 2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C 2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F; 2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E 2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91; 2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90 2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93; 2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92 2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95; 2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94 2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97; 2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96 2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99; 2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98 2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B; 2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A 2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D; 2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C 2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F; 2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E 2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1; 2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0 2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3; 2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2 2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5; 2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4 2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7; 2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6 2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9; 2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8 2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB; 2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA 2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD; 2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC 2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF; 2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE 2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1; 2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0 2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3; 2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2 2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5; 2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4 2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7; 2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6 2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9; 2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8 2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB; 2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA 2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD; 2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC 2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF; 2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE 2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1; 2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0 2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3; 2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2 2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5; 2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4 2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7; 2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6 2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9; 2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8 2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB; 2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA 2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD; 2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC 2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF; 2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE 2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1; 2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0 2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3; 2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2 2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5; 2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4 2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7; 2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6 2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9; 2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8 2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB; 2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA 2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD; 2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC 2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF; 2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE 2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1; 2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0 2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3; 2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2 2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;; 2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;; 2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;; 2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;; 2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;; 2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;; 2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;; 2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC; 2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB 2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE; 2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED 2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;; 2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;; 2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;; 2CF2;COPTIC CAPITAL LETTER BOHAIRIC KHEI;Lu;0;L;;;;;N;;;;2CF3; 2CF3;COPTIC SMALL LETTER BOHAIRIC KHEI;Ll;0;L;;;;;N;;;2CF2;;2CF2 2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;; 2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;; 2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;; 2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;; 2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;; 2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0 2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1 2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2 2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3 2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4 2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5 2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6 2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7 2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8 2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9 2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA 2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB 2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC 2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD 2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE 2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF 2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0 2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1 2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2 2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3 2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4 2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5 2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6 2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7 2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8 2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9 2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA 2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB 2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC 2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD 2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE 2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF 2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0 2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1 2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2 2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3 2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4 2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5 2D27;GEORGIAN SMALL LETTER YN;Ll;0;L;;;;;N;;;10C7;;10C7 2D2D;GEORGIAN SMALL LETTER AEN;Ll;0;L;;;;;N;;;10CD;;10CD 2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;; 2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;; 2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;; 2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;; 2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;; 2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;; 2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;; 2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;; 2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;; 2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;; 2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;; 2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;; 2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;; 2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;; 2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;; 2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;; 2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;; 2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;; 2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;; 2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;; 2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;; 2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;; 2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;; 2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;; 2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;; 2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;; 2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;; 2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;; 2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;; 2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;; 2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;; 2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;; 2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;; 2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;; 2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;; 2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;; 2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;; 2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;; 2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;; 2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;; 2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;; 2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;; 2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;; 2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;; 2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;; 2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;; 2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;; 2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;; 2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;; 2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;; 2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;; 2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;; 2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; 2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; 2D66;TIFINAGH LETTER YE;Lo;0;L;;;;;N;;;;; 2D67;TIFINAGH LETTER YO;Lo;0;L;;;;;N;;;;; 2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L; 2D61;;;;N;;;;; 2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;; 2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;; 2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; 2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; 2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; 2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;; 2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;; 2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;; 2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;; 2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;; 2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;; 2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;; 2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;; 2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;; 2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;; 2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;; 2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;; 2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;; 2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;; 2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;; 2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;; 2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;; 2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;; 2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;; 2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;; 2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;; 2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;; 2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;; 2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;; 2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;; 2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;; 2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;; 2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;; 2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;; 2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;; 2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;; 2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;; 2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;; 2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;; 2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; 2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; 2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; 2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;; 2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;; 2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; 2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; 2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;; 2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;; 2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;; 2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;; 2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;; 2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;; 2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;; 2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;; 2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;; 2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;; 2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;; 2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;; 2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;; 2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;; 2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;; 2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;; 2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;; 2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;; 2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;; 2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;; 2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;; 2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;; 2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;; 2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;; 2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;; 2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;; 2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;; 2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;; 2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;; 2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;; 2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;; 2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;; 2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;; 2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;; 2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;; 2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;; 2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;; 2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;; 2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;; 2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;; 2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;; 2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;; 2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;; 2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;; 2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;; 2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;; 2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;; 2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;; 2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;; 2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;; 2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;; 2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;; 2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;; 2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; 2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;; 2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; 2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;; 2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;; 2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;; 2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;; 2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;; 2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;; 2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;; 2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;; 2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;; 2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; 2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;; 2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;; 2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;; 2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;; 2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;; 2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;; 2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;; 2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;; 2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;; 2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;; 2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;; 2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;; 2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;; 2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;; 2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;; 2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;; 2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;; 2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;; 2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;; 2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;; 2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;; 2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;; 2E30;RING POINT;Po;0;ON;;;;;N;;;;; 2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;; 2E32;TURNED COMMA;Po;0;ON;;;;;N;;;;; 2E33;RAISED DOT;Po;0;ON;;;;;N;;;;; 2E34;RAISED COMMA;Po;0;ON;;;;;N;;;;; 2E35;TURNED SEMICOLON;Po;0;ON;;;;;N;;;;; 2E36;DAGGER WITH LEFT GUARD;Po;0;ON;;;;;N;;;;; 2E37;DAGGER WITH RIGHT GUARD;Po;0;ON;;;;;N;;;;; 2E38;TURNED DAGGER;Po;0;ON;;;;;N;;;;; 2E39;TOP HALF SECTION SIGN;Po;0;ON;;;;;N;;;;; 2E3A;TWO-EM DASH;Pd;0;ON;;;;;N;;;;; 2E3B;THREE-EM DASH;Pd;0;ON;;;;;N;;;;; 2E3C;STENOGRAPHIC FULL STOP;Po;0;ON;;;;;N;;;;; 2E3D;VERTICAL SIX DOTS;Po;0;ON;;;;;N;;;;; 2E3E;WIGGLY VERTICAL LINE;Po;0;ON;;;;;N;;;;; 2E3F;CAPITULUM;Po;0;ON;;;;;N;;;;; 2E40;DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E41;REVERSED COMMA;Po;0;ON;;;;;N;;;;; 2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; 2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; 2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; 2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; 2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; 2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; 2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; 2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; 2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; 2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; 2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; 2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; 2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; 2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; 2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; 2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; 2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; 2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; 2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; 2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; 2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; 2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; 2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; 2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; 2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; 2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; 2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; 2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; 2E9F;CJK RADICAL MOTHER;So;0;ON; 6BCD;;;;N;;;;; 2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; 2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; 2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; 2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; 2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; 2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; 2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; 2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; 2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; 2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; 2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; 2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; 2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; 2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; 2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; 2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; 2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; 2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; 2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; 2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; 2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; 2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; 2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; 2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; 2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; 2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; 2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; 2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; 2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; 2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; 2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; 2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; 2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; 2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; 2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; 2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; 2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; 2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; 2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; 2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; 2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; 2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; 2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; 2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; 2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; 2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; 2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; 2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; 2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; 2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; 2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; 2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; 2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; 2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; 2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; 2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; 2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; 2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; 2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; 2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; 2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; 2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; 2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; 2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; 2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; 2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; 2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; 2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; 2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; 2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; 2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; 2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; 2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; 2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; 2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; 2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; 2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; 2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON; 9F9F;;;;N;;;;; 2F00;KANGXI RADICAL ONE;So;0;ON; 4E00;;;;N;;;;; 2F01;KANGXI RADICAL LINE;So;0;ON; 4E28;;;;N;;;;; 2F02;KANGXI RADICAL DOT;So;0;ON; 4E36;;;;N;;;;; 2F03;KANGXI RADICAL SLASH;So;0;ON; 4E3F;;;;N;;;;; 2F04;KANGXI RADICAL SECOND;So;0;ON; 4E59;;;;N;;;;; 2F05;KANGXI RADICAL HOOK;So;0;ON; 4E85;;;;N;;;;; 2F06;KANGXI RADICAL TWO;So;0;ON; 4E8C;;;;N;;;;; 2F07;KANGXI RADICAL LID;So;0;ON; 4EA0;;;;N;;;;; 2F08;KANGXI RADICAL MAN;So;0;ON; 4EBA;;;;N;;;;; 2F09;KANGXI RADICAL LEGS;So;0;ON; 513F;;;;N;;;;; 2F0A;KANGXI RADICAL ENTER;So;0;ON; 5165;;;;N;;;;; 2F0B;KANGXI RADICAL EIGHT;So;0;ON; 516B;;;;N;;;;; 2F0C;KANGXI RADICAL DOWN BOX;So;0;ON; 5182;;;;N;;;;; 2F0D;KANGXI RADICAL COVER;So;0;ON; 5196;;;;N;;;;; 2F0E;KANGXI RADICAL ICE;So;0;ON; 51AB;;;;N;;;;; 2F0F;KANGXI RADICAL TABLE;So;0;ON; 51E0;;;;N;;;;; 2F10;KANGXI RADICAL OPEN BOX;So;0;ON; 51F5;;;;N;;;;; 2F11;KANGXI RADICAL KNIFE;So;0;ON; 5200;;;;N;;;;; 2F12;KANGXI RADICAL POWER;So;0;ON; 529B;;;;N;;;;; 2F13;KANGXI RADICAL WRAP;So;0;ON; 52F9;;;;N;;;;; 2F14;KANGXI RADICAL SPOON;So;0;ON; 5315;;;;N;;;;; 2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON; 531A;;;;N;;;;; 2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON; 5338;;;;N;;;;; 2F17;KANGXI RADICAL TEN;So;0;ON; 5341;;;;N;;;;; 2F18;KANGXI RADICAL DIVINATION;So;0;ON; 535C;;;;N;;;;; 2F19;KANGXI RADICAL SEAL;So;0;ON; 5369;;;;N;;;;; 2F1A;KANGXI RADICAL CLIFF;So;0;ON; 5382;;;;N;;;;; 2F1B;KANGXI RADICAL PRIVATE;So;0;ON; 53B6;;;;N;;;;; 2F1C;KANGXI RADICAL AGAIN;So;0;ON; 53C8;;;;N;;;;; 2F1D;KANGXI RADICAL MOUTH;So;0;ON; 53E3;;;;N;;;;; 2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON; 56D7;;;;N;;;;; 2F1F;KANGXI RADICAL EARTH;So;0;ON; 571F;;;;N;;;;; 2F20;KANGXI RADICAL SCHOLAR;So;0;ON; 58EB;;;;N;;;;; 2F21;KANGXI RADICAL GO;So;0;ON; 5902;;;;N;;;;; 2F22;KANGXI RADICAL GO SLOWLY;So;0;ON; 590A;;;;N;;;;; 2F23;KANGXI RADICAL EVENING;So;0;ON; 5915;;;;N;;;;; 2F24;KANGXI RADICAL BIG;So;0;ON; 5927;;;;N;;;;; 2F25;KANGXI RADICAL WOMAN;So;0;ON; 5973;;;;N;;;;; 2F26;KANGXI RADICAL CHILD;So;0;ON; 5B50;;;;N;;;;; 2F27;KANGXI RADICAL ROOF;So;0;ON; 5B80;;;;N;;;;; 2F28;KANGXI RADICAL INCH;So;0;ON; 5BF8;;;;N;;;;; 2F29;KANGXI RADICAL SMALL;So;0;ON; 5C0F;;;;N;;;;; 2F2A;KANGXI RADICAL LAME;So;0;ON; 5C22;;;;N;;;;; 2F2B;KANGXI RADICAL CORPSE;So;0;ON; 5C38;;;;N;;;;; 2F2C;KANGXI RADICAL SPROUT;So;0;ON; 5C6E;;;;N;;;;; 2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON; 5C71;;;;N;;;;; 2F2E;KANGXI RADICAL RIVER;So;0;ON; 5DDB;;;;N;;;;; 2F2F;KANGXI RADICAL WORK;So;0;ON; 5DE5;;;;N;;;;; 2F30;KANGXI RADICAL ONESELF;So;0;ON; 5DF1;;;;N;;;;; 2F31;KANGXI RADICAL TURBAN;So;0;ON; 5DFE;;;;N;;;;; 2F32;KANGXI RADICAL DRY;So;0;ON; 5E72;;;;N;;;;; 2F33;KANGXI RADICAL SHORT THREAD;So;0;ON; 5E7A;;;;N;;;;; 2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON; 5E7F;;;;N;;;;; 2F35;KANGXI RADICAL LONG STRIDE;So;0;ON; 5EF4;;;;N;;;;; 2F36;KANGXI RADICAL TWO HANDS;So;0;ON; 5EFE;;;;N;;;;; 2F37;KANGXI RADICAL SHOOT;So;0;ON; 5F0B;;;;N;;;;; 2F38;KANGXI RADICAL BOW;So;0;ON; 5F13;;;;N;;;;; 2F39;KANGXI RADICAL SNOUT;So;0;ON; 5F50;;;;N;;;;; 2F3A;KANGXI RADICAL BRISTLE;So;0;ON; 5F61;;;;N;;;;; 2F3B;KANGXI RADICAL STEP;So;0;ON; 5F73;;;;N;;;;; 2F3C;KANGXI RADICAL HEART;So;0;ON; 5FC3;;;;N;;;;; 2F3D;KANGXI RADICAL HALBERD;So;0;ON; 6208;;;;N;;;;; 2F3E;KANGXI RADICAL DOOR;So;0;ON; 6236;;;;N;;;;; 2F3F;KANGXI RADICAL HAND;So;0;ON; 624B;;;;N;;;;; 2F40;KANGXI RADICAL BRANCH;So;0;ON; 652F;;;;N;;;;; 2F41;KANGXI RADICAL RAP;So;0;ON; 6534;;;;N;;;;; 2F42;KANGXI RADICAL SCRIPT;So;0;ON; 6587;;;;N;;;;; 2F43;KANGXI RADICAL DIPPER;So;0;ON; 6597;;;;N;;;;; 2F44;KANGXI RADICAL AXE;So;0;ON; 65A4;;;;N;;;;; 2F45;KANGXI RADICAL SQUARE;So;0;ON; 65B9;;;;N;;;;; 2F46;KANGXI RADICAL NOT;So;0;ON; 65E0;;;;N;;;;; 2F47;KANGXI RADICAL SUN;So;0;ON; 65E5;;;;N;;;;; 2F48;KANGXI RADICAL SAY;So;0;ON; 66F0;;;;N;;;;; 2F49;KANGXI RADICAL MOON;So;0;ON; 6708;;;;N;;;;; 2F4A;KANGXI RADICAL TREE;So;0;ON; 6728;;;;N;;;;; 2F4B;KANGXI RADICAL LACK;So;0;ON; 6B20;;;;N;;;;; 2F4C;KANGXI RADICAL STOP;So;0;ON; 6B62;;;;N;;;;; 2F4D;KANGXI RADICAL DEATH;So;0;ON; 6B79;;;;N;;;;; 2F4E;KANGXI RADICAL WEAPON;So;0;ON; 6BB3;;;;N;;;;; 2F4F;KANGXI RADICAL DO NOT;So;0;ON; 6BCB;;;;N;;;;; 2F50;KANGXI RADICAL COMPARE;So;0;ON; 6BD4;;;;N;;;;; 2F51;KANGXI RADICAL FUR;So;0;ON; 6BDB;;;;N;;;;; 2F52;KANGXI RADICAL CLAN;So;0;ON; 6C0F;;;;N;;;;; 2F53;KANGXI RADICAL STEAM;So;0;ON; 6C14;;;;N;;;;; 2F54;KANGXI RADICAL WATER;So;0;ON; 6C34;;;;N;;;;; 2F55;KANGXI RADICAL FIRE;So;0;ON; 706B;;;;N;;;;; 2F56;KANGXI RADICAL CLAW;So;0;ON; 722A;;;;N;;;;; 2F57;KANGXI RADICAL FATHER;So;0;ON; 7236;;;;N;;;;; 2F58;KANGXI RADICAL DOUBLE X;So;0;ON; 723B;;;;N;;;;; 2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON; 723F;;;;N;;;;; 2F5A;KANGXI RADICAL SLICE;So;0;ON; 7247;;;;N;;;;; 2F5B;KANGXI RADICAL FANG;So;0;ON; 7259;;;;N;;;;; 2F5C;KANGXI RADICAL COW;So;0;ON; 725B;;;;N;;;;; 2F5D;KANGXI RADICAL DOG;So;0;ON; 72AC;;;;N;;;;; 2F5E;KANGXI RADICAL PROFOUND;So;0;ON; 7384;;;;N;;;;; 2F5F;KANGXI RADICAL JADE;So;0;ON; 7389;;;;N;;;;; 2F60;KANGXI RADICAL MELON;So;0;ON; 74DC;;;;N;;;;; 2F61;KANGXI RADICAL TILE;So;0;ON; 74E6;;;;N;;;;; 2F62;KANGXI RADICAL SWEET;So;0;ON; 7518;;;;N;;;;; 2F63;KANGXI RADICAL LIFE;So;0;ON; 751F;;;;N;;;;; 2F64;KANGXI RADICAL USE;So;0;ON; 7528;;;;N;;;;; 2F65;KANGXI RADICAL FIELD;So;0;ON; 7530;;;;N;;;;; 2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON; 758B;;;;N;;;;; 2F67;KANGXI RADICAL SICKNESS;So;0;ON; 7592;;;;N;;;;; 2F68;KANGXI RADICAL DOTTED TENT;So;0;ON; 7676;;;;N;;;;; 2F69;KANGXI RADICAL WHITE;So;0;ON; 767D;;;;N;;;;; 2F6A;KANGXI RADICAL SKIN;So;0;ON; 76AE;;;;N;;;;; 2F6B;KANGXI RADICAL DISH;So;0;ON; 76BF;;;;N;;;;; 2F6C;KANGXI RADICAL EYE;So;0;ON; 76EE;;;;N;;;;; 2F6D;KANGXI RADICAL SPEAR;So;0;ON; 77DB;;;;N;;;;; 2F6E;KANGXI RADICAL ARROW;So;0;ON; 77E2;;;;N;;;;; 2F6F;KANGXI RADICAL STONE;So;0;ON; 77F3;;;;N;;;;; 2F70;KANGXI RADICAL SPIRIT;So;0;ON; 793A;;;;N;;;;; 2F71;KANGXI RADICAL TRACK;So;0;ON; 79B8;;;;N;;;;; 2F72;KANGXI RADICAL GRAIN;So;0;ON; 79BE;;;;N;;;;; 2F73;KANGXI RADICAL CAVE;So;0;ON; 7A74;;;;N;;;;; 2F74;KANGXI RADICAL STAND;So;0;ON; 7ACB;;;;N;;;;; 2F75;KANGXI RADICAL BAMBOO;So;0;ON; 7AF9;;;;N;;;;; 2F76;KANGXI RADICAL RICE;So;0;ON; 7C73;;;;N;;;;; 2F77;KANGXI RADICAL SILK;So;0;ON; 7CF8;;;;N;;;;; 2F78;KANGXI RADICAL JAR;So;0;ON; 7F36;;;;N;;;;; 2F79;KANGXI RADICAL NET;So;0;ON; 7F51;;;;N;;;;; 2F7A;KANGXI RADICAL SHEEP;So;0;ON; 7F8A;;;;N;;;;; 2F7B;KANGXI RADICAL FEATHER;So;0;ON; 7FBD;;;;N;;;;; 2F7C;KANGXI RADICAL OLD;So;0;ON; 8001;;;;N;;;;; 2F7D;KANGXI RADICAL AND;So;0;ON; 800C;;;;N;;;;; 2F7E;KANGXI RADICAL PLOW;So;0;ON; 8012;;;;N;;;;; 2F7F;KANGXI RADICAL EAR;So;0;ON; 8033;;;;N;;;;; 2F80;KANGXI RADICAL BRUSH;So;0;ON; 807F;;;;N;;;;; 2F81;KANGXI RADICAL MEAT;So;0;ON; 8089;;;;N;;;;; 2F82;KANGXI RADICAL MINISTER;So;0;ON; 81E3;;;;N;;;;; 2F83;KANGXI RADICAL SELF;So;0;ON; 81EA;;;;N;;;;; 2F84;KANGXI RADICAL ARRIVE;So;0;ON; 81F3;;;;N;;;;; 2F85;KANGXI RADICAL MORTAR;So;0;ON; 81FC;;;;N;;;;; 2F86;KANGXI RADICAL TONGUE;So;0;ON; 820C;;;;N;;;;; 2F87;KANGXI RADICAL OPPOSE;So;0;ON; 821B;;;;N;;;;; 2F88;KANGXI RADICAL BOAT;So;0;ON; 821F;;;;N;;;;; 2F89;KANGXI RADICAL STOPPING;So;0;ON; 826E;;;;N;;;;; 2F8A;KANGXI RADICAL COLOR;So;0;ON; 8272;;;;N;;;;; 2F8B;KANGXI RADICAL GRASS;So;0;ON; 8278;;;;N;;;;; 2F8C;KANGXI RADICAL TIGER;So;0;ON; 864D;;;;N;;;;; 2F8D;KANGXI RADICAL INSECT;So;0;ON; 866B;;;;N;;;;; 2F8E;KANGXI RADICAL BLOOD;So;0;ON; 8840;;;;N;;;;; 2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON; 884C;;;;N;;;;; 2F90;KANGXI RADICAL CLOTHES;So;0;ON; 8863;;;;N;;;;; 2F91;KANGXI RADICAL WEST;So;0;ON; 897E;;;;N;;;;; 2F92;KANGXI RADICAL SEE;So;0;ON; 898B;;;;N;;;;; 2F93;KANGXI RADICAL HORN;So;0;ON; 89D2;;;;N;;;;; 2F94;KANGXI RADICAL SPEECH;So;0;ON; 8A00;;;;N;;;;; 2F95;KANGXI RADICAL VALLEY;So;0;ON; 8C37;;;;N;;;;; 2F96;KANGXI RADICAL BEAN;So;0;ON; 8C46;;;;N;;;;; 2F97;KANGXI RADICAL PIG;So;0;ON; 8C55;;;;N;;;;; 2F98;KANGXI RADICAL BADGER;So;0;ON; 8C78;;;;N;;;;; 2F99;KANGXI RADICAL SHELL;So;0;ON; 8C9D;;;;N;;;;; 2F9A;KANGXI RADICAL RED;So;0;ON; 8D64;;;;N;;;;; 2F9B;KANGXI RADICAL RUN;So;0;ON; 8D70;;;;N;;;;; 2F9C;KANGXI RADICAL FOOT;So;0;ON; 8DB3;;;;N;;;;; 2F9D;KANGXI RADICAL BODY;So;0;ON; 8EAB;;;;N;;;;; 2F9E;KANGXI RADICAL CART;So;0;ON; 8ECA;;;;N;;;;; 2F9F;KANGXI RADICAL BITTER;So;0;ON; 8F9B;;;;N;;;;; 2FA0;KANGXI RADICAL MORNING;So;0;ON; 8FB0;;;;N;;;;; 2FA1;KANGXI RADICAL WALK;So;0;ON; 8FB5;;;;N;;;;; 2FA2;KANGXI RADICAL CITY;So;0;ON; 9091;;;;N;;;;; 2FA3;KANGXI RADICAL WINE;So;0;ON; 9149;;;;N;;;;; 2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON; 91C6;;;;N;;;;; 2FA5;KANGXI RADICAL VILLAGE;So;0;ON; 91CC;;;;N;;;;; 2FA6;KANGXI RADICAL GOLD;So;0;ON; 91D1;;;;N;;;;; 2FA7;KANGXI RADICAL LONG;So;0;ON; 9577;;;;N;;;;; 2FA8;KANGXI RADICAL GATE;So;0;ON; 9580;;;;N;;;;; 2FA9;KANGXI RADICAL MOUND;So;0;ON; 961C;;;;N;;;;; 2FAA;KANGXI RADICAL SLAVE;So;0;ON; 96B6;;;;N;;;;; 2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON; 96B9;;;;N;;;;; 2FAC;KANGXI RADICAL RAIN;So;0;ON; 96E8;;;;N;;;;; 2FAD;KANGXI RADICAL BLUE;So;0;ON; 9751;;;;N;;;;; 2FAE;KANGXI RADICAL WRONG;So;0;ON; 975E;;;;N;;;;; 2FAF;KANGXI RADICAL FACE;So;0;ON; 9762;;;;N;;;;; 2FB0;KANGXI RADICAL LEATHER;So;0;ON; 9769;;;;N;;;;; 2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON; 97CB;;;;N;;;;; 2FB2;KANGXI RADICAL LEEK;So;0;ON; 97ED;;;;N;;;;; 2FB3;KANGXI RADICAL SOUND;So;0;ON; 97F3;;;;N;;;;; 2FB4;KANGXI RADICAL LEAF;So;0;ON; 9801;;;;N;;;;; 2FB5;KANGXI RADICAL WIND;So;0;ON; 98A8;;;;N;;;;; 2FB6;KANGXI RADICAL FLY;So;0;ON; 98DB;;;;N;;;;; 2FB7;KANGXI RADICAL EAT;So;0;ON; 98DF;;;;N;;;;; 2FB8;KANGXI RADICAL HEAD;So;0;ON; 9996;;;;N;;;;; 2FB9;KANGXI RADICAL FRAGRANT;So;0;ON; 9999;;;;N;;;;; 2FBA;KANGXI RADICAL HORSE;So;0;ON; 99AC;;;;N;;;;; 2FBB;KANGXI RADICAL BONE;So;0;ON; 9AA8;;;;N;;;;; 2FBC;KANGXI RADICAL TALL;So;0;ON; 9AD8;;;;N;;;;; 2FBD;KANGXI RADICAL HAIR;So;0;ON; 9ADF;;;;N;;;;; 2FBE;KANGXI RADICAL FIGHT;So;0;ON; 9B25;;;;N;;;;; 2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON; 9B2F;;;;N;;;;; 2FC0;KANGXI RADICAL CAULDRON;So;0;ON; 9B32;;;;N;;;;; 2FC1;KANGXI RADICAL GHOST;So;0;ON; 9B3C;;;;N;;;;; 2FC2;KANGXI RADICAL FISH;So;0;ON; 9B5A;;;;N;;;;; 2FC3;KANGXI RADICAL BIRD;So;0;ON; 9CE5;;;;N;;;;; 2FC4;KANGXI RADICAL SALT;So;0;ON; 9E75;;;;N;;;;; 2FC5;KANGXI RADICAL DEER;So;0;ON; 9E7F;;;;N;;;;; 2FC6;KANGXI RADICAL WHEAT;So;0;ON; 9EA5;;;;N;;;;; 2FC7;KANGXI RADICAL HEMP;So;0;ON; 9EBB;;;;N;;;;; 2FC8;KANGXI RADICAL YELLOW;So;0;ON; 9EC3;;;;N;;;;; 2FC9;KANGXI RADICAL MILLET;So;0;ON; 9ECD;;;;N;;;;; 2FCA;KANGXI RADICAL BLACK;So;0;ON; 9ED1;;;;N;;;;; 2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON; 9EF9;;;;N;;;;; 2FCC;KANGXI RADICAL FROG;So;0;ON; 9EFD;;;;N;;;;; 2FCD;KANGXI RADICAL TRIPOD;So;0;ON; 9F0E;;;;N;;;;; 2FCE;KANGXI RADICAL DRUM;So;0;ON; 9F13;;;;N;;;;; 2FCF;KANGXI RADICAL RAT;So;0;ON; 9F20;;;;N;;;;; 2FD0;KANGXI RADICAL NOSE;So;0;ON; 9F3B;;;;N;;;;; 2FD1;KANGXI RADICAL EVEN;So;0;ON; 9F4A;;;;N;;;;; 2FD2;KANGXI RADICAL TOOTH;So;0;ON; 9F52;;;;N;;;;; 2FD3;KANGXI RADICAL DRAGON;So;0;ON; 9F8D;;;;N;;;;; 2FD4;KANGXI RADICAL TURTLE;So;0;ON; 9F9C;;;;N;;;;; 2FD5;KANGXI RADICAL FLUTE;So;0;ON; 9FA0;;;;N;;;;; 2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; 2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; 2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; 2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; 2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; 2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; 2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; 2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; 2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; 2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; 2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; 2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; 3000;IDEOGRAPHIC SPACE;Zs;0;WS; 0020;;;;N;;;;; 3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; 3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; 3003;DITTO MARK;Po;0;ON;;;;;N;;;;; 3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; 3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; 3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; 3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; 3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; 300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; 300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; 300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; 300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; 300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; 300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; 3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; 3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; 3012;POSTAL MARK;So;0;ON;;;;;N;;;;; 3013;GETA MARK;So;0;ON;;;;;N;;;;; 3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; 3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; 3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; 3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; 3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; 3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; 301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; 301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; 301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; 301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; 3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; 3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; 3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; 3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; 3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; 3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; 3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; 3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; 3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; 302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; 302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; 302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; 302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; 302E;HANGUL SINGLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; 302F;HANGUL DOUBLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; 3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; 3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; 3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; 3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; 3036;CIRCLED POSTAL MARK;So;0;ON; 3012;;;;N;;;;; 3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; 3038;HANGZHOU NUMERAL TEN;Nl;0;L; 5341;;;10;N;;;;; 3039;HANGZHOU NUMERAL TWENTY;Nl;0;L; 5344;;;20;N;;;;; 303A;HANGZHOU NUMERAL THIRTY;Nl;0;L; 5345;;;30;N;;;;; 303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 303C;MASU MARK;Lo;0;L;;;;;N;;;;; 303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; 303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; 303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; 3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; 3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; 3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; 3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; 3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; 304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; 304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; 304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; 304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; 304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; 3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; 3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; 3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; 3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; 3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; 3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; 3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; 3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; 3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; 3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; 305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; 305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; 305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; 305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; 305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; 305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; 3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; 3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; 3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; 3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; 3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; 3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; 3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; 3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; 3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; 306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; 306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; 306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; 306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; 306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; 306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; 3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; 3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; 3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; 3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; 3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; 3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; 3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; 3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; 3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; 3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; 307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; 307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; 307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; 307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; 307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; 307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; 3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; 3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; 3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; 3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; 3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; 3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; 3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; 308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; 308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; 308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; 308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; 308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; 3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; 3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; 3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; 3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; 3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; 3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; 309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; 309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON; 0020 3099;;;;N;;;;; 309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON; 0020 309A;;;;N;;;;; 309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; 309F;HIRAGANA DIGRAPH YORI;Lo;0;L; 3088 308A;;;;N;;;;; 30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; 30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; 30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; 30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; 30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; 30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; 30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; 30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; 30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; 30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; 30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; 30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; 30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; 30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; 30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; 30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; 30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; 30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; 30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; 30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; 30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; 30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; 30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; 30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; 30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; 30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; 30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; 30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; 30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; 30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; 30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; 30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; 30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; 30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; 30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; 30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; 30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; 30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; 30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; 30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; 30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; 30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; 30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; 30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; 30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; 30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; 30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; 30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; 30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; 30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; 30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; 30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; 30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; 30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; 30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; 30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; 30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; 30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; 30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; 30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; 30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; 30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; 30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; 30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; 30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; 30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; 30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; 30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; 30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; 30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; 30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; 30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; 30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; 30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; 30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; 30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; 30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; 30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; 30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;; 30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; 30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; 30FF;KATAKANA DIGRAPH KOTO;Lo;0;L; 30B3 30C8;;;;N;;;;; 3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; 3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; 3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; 3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; 3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; 310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; 310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; 310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; 310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; 310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; 310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; 3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; 3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; 3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; 3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; 3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; 3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; 3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; 3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; 3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; 3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; 311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; 311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; 311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; 311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; 311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; 311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; 3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; 3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; 3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; 3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; 3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; 3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; 3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; 3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; 3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; 3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; 312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L; 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L; 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; 3134;HANGUL LETTER NIEUN;Lo;0;L; 1102;;;;N;;;;; 3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; 3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; 3137;HANGUL LETTER TIKEUT;Lo;0;L; 1103;;;;N;HANGUL LETTER DIGEUD;;;; 3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L; 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; 3139;HANGUL LETTER RIEUL;Lo;0;L; 1105;;;;N;HANGUL LETTER LIEUL;;;; 313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; 313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; 313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; 313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L; 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; 313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; 313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; 3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; 3141;HANGUL LETTER MIEUM;Lo;0;L; 1106;;;;N;;;;; 3142;HANGUL LETTER PIEUP;Lo;0;L; 1107;;;;N;HANGUL LETTER BIEUB;;;; 3143;HANGUL LETTER SSANGPIEUP;Lo;0;L; 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; 3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L; 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; 3145;HANGUL LETTER SIOS;Lo;0;L; 1109;;;;N;;;;; 3146;HANGUL LETTER SSANGSIOS;Lo;0;L; 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; 3147;HANGUL LETTER IEUNG;Lo;0;L; 110B;;;;N;;;;; 3148;HANGUL LETTER CIEUC;Lo;0;L; 110C;;;;N;HANGUL LETTER JIEUJ;;;; 3149;HANGUL LETTER SSANGCIEUC;Lo;0;L; 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; 314A;HANGUL LETTER CHIEUCH;Lo;0;L; 110E;;;;N;HANGUL LETTER CIEUC;;;; 314B;HANGUL LETTER KHIEUKH;Lo;0;L; 110F;;;;N;HANGUL LETTER KIYEOK;;;; 314C;HANGUL LETTER THIEUTH;Lo;0;L; 1110;;;;N;HANGUL LETTER TIEUT;;;; 314D;HANGUL LETTER PHIEUPH;Lo;0;L; 1111;;;;N;HANGUL LETTER PIEUP;;;; 314E;HANGUL LETTER HIEUH;Lo;0;L; 1112;;;;N;;;;; 314F;HANGUL LETTER A;Lo;0;L; 1161;;;;N;;;;; 3150;HANGUL LETTER AE;Lo;0;L; 1162;;;;N;;;;; 3151;HANGUL LETTER YA;Lo;0;L; 1163;;;;N;;;;; 3152;HANGUL LETTER YAE;Lo;0;L; 1164;;;;N;;;;; 3153;HANGUL LETTER EO;Lo;0;L; 1165;;;;N;;;;; 3154;HANGUL LETTER E;Lo;0;L; 1166;;;;N;;;;; 3155;HANGUL LETTER YEO;Lo;0;L; 1167;;;;N;;;;; 3156;HANGUL LETTER YE;Lo;0;L; 1168;;;;N;;;;; 3157;HANGUL LETTER O;Lo;0;L; 1169;;;;N;;;;; 3158;HANGUL LETTER WA;Lo;0;L; 116A;;;;N;;;;; 3159;HANGUL LETTER WAE;Lo;0;L; 116B;;;;N;;;;; 315A;HANGUL LETTER OE;Lo;0;L; 116C;;;;N;;;;; 315B;HANGUL LETTER YO;Lo;0;L; 116D;;;;N;;;;; 315C;HANGUL LETTER U;Lo;0;L; 116E;;;;N;;;;; 315D;HANGUL LETTER WEO;Lo;0;L; 116F;;;;N;;;;; 315E;HANGUL LETTER WE;Lo;0;L; 1170;;;;N;;;;; 315F;HANGUL LETTER WI;Lo;0;L; 1171;;;;N;;;;; 3160;HANGUL LETTER YU;Lo;0;L; 1172;;;;N;;;;; 3161;HANGUL LETTER EU;Lo;0;L; 1173;;;;N;;;;; 3162;HANGUL LETTER YI;Lo;0;L; 1174;;;;N;;;;; 3163;HANGUL LETTER I;Lo;0;L; 1175;;;;N;;;;; 3164;HANGUL FILLER;Lo;0;L; 1160;;;;N;HANGUL CAE OM;;;; 3165;HANGUL LETTER SSANGNIEUN;Lo;0;L; 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; 3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L; 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; 3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L; 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; 3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L; 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; 3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L; 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; 316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L; 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; 316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L; 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; 316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L; 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; 316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L; 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; 316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L; 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; 316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L; 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; 3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L; 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; 3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L; 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; 3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L; 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; 3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L; 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; 3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L; 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; 3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L; 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; 3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L; 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; 3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L; 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; 3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L; 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; 3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L; 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; 317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L; 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; 317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L; 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; 317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L; 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; 317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L; 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; 317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L; 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; 317F;HANGUL LETTER PANSIOS;Lo;0;L; 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; 3180;HANGUL LETTER SSANGIEUNG;Lo;0;L; 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; 3181;HANGUL LETTER YESIEUNG;Lo;0;L; 114C;;;;N;HANGUL LETTER NGIEUNG;;;; 3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L; 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; 3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L; 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; 3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L; 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; 3185;HANGUL LETTER SSANGHIEUH;Lo;0;L; 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; 3186;HANGUL LETTER YEORINHIEUH;Lo;0;L; 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; 3187;HANGUL LETTER YO-YA;Lo;0;L; 1184;;;;N;HANGUL LETTER YOYA;;;; 3188;HANGUL LETTER YO-YAE;Lo;0;L; 1185;;;;N;HANGUL LETTER YOYAE;;;; 3189;HANGUL LETTER YO-I;Lo;0;L; 1188;;;;N;HANGUL LETTER YOI;;;; 318A;HANGUL LETTER YU-YEO;Lo;0;L; 1191;;;;N;HANGUL LETTER YUYEO;;;; 318B;HANGUL LETTER YU-YE;Lo;0;L; 1192;;;;N;HANGUL LETTER YUYE;;;; 318C;HANGUL LETTER YU-I;Lo;0;L; 1194;;;;N;HANGUL LETTER YUI;;;; 318D;HANGUL LETTER ARAEA;Lo;0;L; 119E;;;;N;HANGUL LETTER ALAE A;;;; 318E;HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; 3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;; 3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;; 3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L; 4E00;;;1;N;KAERITEN ITI;;;; 3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L; 4E8C;;;2;N;KAERITEN NI;;;; 3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L; 4E09;;;3;N;KAERITEN SAN;;;; 3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L; 56DB;;;4;N;KAERITEN SI;;;; 3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L; 4E0A;;;;N;KAERITEN ZYOU;;;; 3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L; 4E2D;;;;N;KAERITEN TYUU;;;; 3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L; 4E0B;;;;N;KAERITEN GE;;;; 3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L; 7532;;;;N;KAERITEN KOU;;;; 319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L; 4E59;;;;N;KAERITEN OTU;;;; 319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L; 4E19;;;;N;KAERITEN HEI;;;; 319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L; 4E01;;;;N;KAERITEN TEI;;;; 319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L; 5929;;;;N;KAERITEN TEN;;;; 319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L; 5730;;;;N;KAERITEN TI;;;; 319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L; 4EBA;;;;N;KAERITEN ZIN;;;; 31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; 31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; 31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; 31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; 31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; 31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; 31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; 31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; 31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; 31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; 31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; 31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; 31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; 31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; 31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; 31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; 31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; 31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; 31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; 31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; 31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; 31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; 31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; 31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; 31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;; 31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;; 31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;; 31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; 31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; 31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; 31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;; 31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;; 31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;; 31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;; 31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;; 31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;; 31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;; 31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;; 31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;; 31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;; 31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;; 31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;; 31CF;CJK STROKE N;So;0;ON;;;;;N;;;;; 31D0;CJK STROKE H;So;0;ON;;;;;N;;;;; 31D1;CJK STROKE S;So;0;ON;;;;;N;;;;; 31D2;CJK STROKE P;So;0;ON;;;;;N;;;;; 31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;; 31D4;CJK STROKE D;So;0;ON;;;;;N;;;;; 31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;; 31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;; 31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;; 31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;; 31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;; 31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;; 31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;; 31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;; 31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;; 31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;; 31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;; 31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;; 31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;; 31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;; 31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;; 31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; 31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; 31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; 31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; 31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; 31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; 31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; 31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; 31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; 31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; 31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; 31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; 31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; 31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; 31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; 31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; 3200;PARENTHESIZED HANGUL KIYEOK;So;0;L; 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; 3201;PARENTHESIZED HANGUL NIEUN;So;0;L; 0028 1102 0029;;;;N;;;;; 3202;PARENTHESIZED HANGUL TIKEUT;So;0;L; 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; 3203;PARENTHESIZED HANGUL RIEUL;So;0;L; 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; 3204;PARENTHESIZED HANGUL MIEUM;So;0;L; 0028 1106 0029;;;;N;;;;; 3205;PARENTHESIZED HANGUL PIEUP;So;0;L; 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; 3206;PARENTHESIZED HANGUL SIOS;So;0;L; 0028 1109 0029;;;;N;;;;; 3207;PARENTHESIZED HANGUL IEUNG;So;0;L; 0028 110B 0029;;;;N;;;;; 3208;PARENTHESIZED HANGUL CIEUC;So;0;L; 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; 3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L; 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; 320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L; 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; 320B;PARENTHESIZED HANGUL THIEUTH;So;0;L; 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; 320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L; 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; 320D;PARENTHESIZED HANGUL HIEUH;So;0;L; 0028 1112 0029;;;;N;;;;; 320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L; 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; 320F;PARENTHESIZED HANGUL NIEUN A;So;0;L; 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; 3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L; 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; 3211;PARENTHESIZED HANGUL RIEUL A;So;0;L; 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; 3212;PARENTHESIZED HANGUL MIEUM A;So;0;L; 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; 3213;PARENTHESIZED HANGUL PIEUP A;So;0;L; 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; 3214;PARENTHESIZED HANGUL SIOS A;So;0;L; 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; 3215;PARENTHESIZED HANGUL IEUNG A;So;0;L; 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; 3216;PARENTHESIZED HANGUL CIEUC A;So;0;L; 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; 3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L; 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; 3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L; 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; 3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L; 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; 321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L; 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; 321B;PARENTHESIZED HANGUL HIEUH A;So;0;L; 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; 321C;PARENTHESIZED HANGUL CIEUC U;So;0;L; 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; 321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON; 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;; 321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON; 0028 110B 1169 1112 116E 0029;;;;N;;;;; 3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L; 0028 4E00 0029;;;1;N;;;;; 3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L; 0028 4E8C 0029;;;2;N;;;;; 3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L; 0028 4E09 0029;;;3;N;;;;; 3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L; 0028 56DB 0029;;;4;N;;;;; 3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L; 0028 4E94 0029;;;5;N;;;;; 3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L; 0028 516D 0029;;;6;N;;;;; 3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L; 0028 4E03 0029;;;7;N;;;;; 3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L; 0028 516B 0029;;;8;N;;;;; 3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L; 0028 4E5D 0029;;;9;N;;;;; 3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L; 0028 5341 0029;;;10;N;;;;; 322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L; 0028 6708 0029;;;;N;;;;; 322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L; 0028 706B 0029;;;;N;;;;; 322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L; 0028 6C34 0029;;;;N;;;;; 322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L; 0028 6728 0029;;;;N;;;;; 322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L; 0028 91D1 0029;;;;N;;;;; 322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L; 0028 571F 0029;;;;N;;;;; 3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L; 0028 65E5 0029;;;;N;;;;; 3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L; 0028 682A 0029;;;;N;;;;; 3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L; 0028 6709 0029;;;;N;;;;; 3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L; 0028 793E 0029;;;;N;;;;; 3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L; 0028 540D 0029;;;;N;;;;; 3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L; 0028 7279 0029;;;;N;;;;; 3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L; 0028 8CA1 0029;;;;N;;;;; 3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L; 0028 795D 0029;;;;N;;;;; 3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L; 0028 52B4 0029;;;;N;;;;; 3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L; 0028 4EE3 0029;;;;N;;;;; 323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L; 0028 547C 0029;;;;N;;;;; 323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L; 0028 5B66 0029;;;;N;;;;; 323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L; 0028 76E3 0029;;;;N;;;;; 323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L; 0028 4F01 0029;;;;N;;;;; 323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L; 0028 8CC7 0029;;;;N;;;;; 323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L; 0028 5354 0029;;;;N;;;;; 3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L; 0028 796D 0029;;;;N;;;;; 3241;PARENTHESIZED IDEOGRAPH REST;So;0;L; 0028 4F11 0029;;;;N;;;;; 3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L; 0028 81EA 0029;;;;N;;;;; 3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L; 0028 81F3 0029;;;;N;;;;; 3244;CIRCLED IDEOGRAPH QUESTION;So;0;L; 554F;;;;N;;;;; 3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L; 5E7C;;;;N;;;;; 3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L; 6587;;;;N;;;;; 3247;CIRCLED IDEOGRAPH KOTO;So;0;L; 7B8F;;;;N;;;;; 3248;CIRCLED NUMBER TEN ON BLACK SQUARE;No;0;L;;;;10;N;;;;; 3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;No;0;L;;;;20;N;;;;; 324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;No;0;L;;;;30;N;;;;; 324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;No;0;L;;;;40;N;;;;; 324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;No;0;L;;;;50;N;;;;; 324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;No;0;L;;;;60;N;;;;; 324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;No;0;L;;;;70;N;;;;; 324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;No;0;L;;;;80;N;;;;; 3250;PARTNERSHIP SIGN;So;0;ON; 0050 0054 0045;;;;N;;;;; 3251;CIRCLED NUMBER TWENTY ONE;No;0;ON; 0032 0031;;;21;N;;;;; 3252;CIRCLED NUMBER TWENTY TWO;No;0;ON; 0032 0032;;;22;N;;;;; 3253;CIRCLED NUMBER TWENTY THREE;No;0;ON; 0032 0033;;;23;N;;;;; 3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON; 0032 0034;;;24;N;;;;; 3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON; 0032 0035;;;25;N;;;;; 3256;CIRCLED NUMBER TWENTY SIX;No;0;ON; 0032 0036;;;26;N;;;;; 3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON; 0032 0037;;;27;N;;;;; 3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON; 0032 0038;;;28;N;;;;; 3259;CIRCLED NUMBER TWENTY NINE;No;0;ON; 0032 0039;;;29;N;;;;; 325A;CIRCLED NUMBER THIRTY;No;0;ON; 0033 0030;;;30;N;;;;; 325B;CIRCLED NUMBER THIRTY ONE;No;0;ON; 0033 0031;;;31;N;;;;; 325C;CIRCLED NUMBER THIRTY TWO;No;0;ON; 0033 0032;;;32;N;;;;; 325D;CIRCLED NUMBER THIRTY THREE;No;0;ON; 0033 0033;;;33;N;;;;; 325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON; 0033 0034;;;34;N;;;;; 325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON; 0033 0035;;;35;N;;;;; 3260;CIRCLED HANGUL KIYEOK;So;0;L; 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; 3261;CIRCLED HANGUL NIEUN;So;0;L; 1102;;;;N;;;;; 3262;CIRCLED HANGUL TIKEUT;So;0;L; 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; 3263;CIRCLED HANGUL RIEUL;So;0;L; 1105;;;;N;CIRCLED HANGUL LIEUL;;;; 3264;CIRCLED HANGUL MIEUM;So;0;L; 1106;;;;N;;;;; 3265;CIRCLED HANGUL PIEUP;So;0;L; 1107;;;;N;CIRCLED HANGUL BIEUB;;;; 3266;CIRCLED HANGUL SIOS;So;0;L; 1109;;;;N;;;;; 3267;CIRCLED HANGUL IEUNG;So;0;L; 110B;;;;N;;;;; 3268;CIRCLED HANGUL CIEUC;So;0;L; 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; 3269;CIRCLED HANGUL CHIEUCH;So;0;L; 110E;;;;N;CIRCLED HANGUL CIEUC;;;; 326A;CIRCLED HANGUL KHIEUKH;So;0;L; 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; 326B;CIRCLED HANGUL THIEUTH;So;0;L; 1110;;;;N;CIRCLED HANGUL TIEUT;;;; 326C;CIRCLED HANGUL PHIEUPH;So;0;L; 1111;;;;N;CIRCLED HANGUL PIEUP;;;; 326D;CIRCLED HANGUL HIEUH;So;0;L; 1112;;;;N;;;;; 326E;CIRCLED HANGUL KIYEOK A;So;0;L; 1100 1161;;;;N;CIRCLED HANGUL GA;;;; 326F;CIRCLED HANGUL NIEUN A;So;0;L; 1102 1161;;;;N;CIRCLED HANGUL NA;;;; 3270;CIRCLED HANGUL TIKEUT A;So;0;L; 1103 1161;;;;N;CIRCLED HANGUL DA;;;; 3271;CIRCLED HANGUL RIEUL A;So;0;L; 1105 1161;;;;N;CIRCLED HANGUL LA;;;; 3272;CIRCLED HANGUL MIEUM A;So;0;L; 1106 1161;;;;N;CIRCLED HANGUL MA;;;; 3273;CIRCLED HANGUL PIEUP A;So;0;L; 1107 1161;;;;N;CIRCLED HANGUL BA;;;; 3274;CIRCLED HANGUL SIOS A;So;0;L; 1109 1161;;;;N;CIRCLED HANGUL SA;;;; 3275;CIRCLED HANGUL IEUNG A;So;0;L; 110B 1161;;;;N;CIRCLED HANGUL A;;;; 3276;CIRCLED HANGUL CIEUC A;So;0;L; 110C 1161;;;;N;CIRCLED HANGUL JA;;;; 3277;CIRCLED HANGUL CHIEUCH A;So;0;L; 110E 1161;;;;N;CIRCLED HANGUL CA;;;; 3278;CIRCLED HANGUL KHIEUKH A;So;0;L; 110F 1161;;;;N;CIRCLED HANGUL KA;;;; 3279;CIRCLED HANGUL THIEUTH A;So;0;L; 1110 1161;;;;N;CIRCLED HANGUL TA;;;; 327A;CIRCLED HANGUL PHIEUPH A;So;0;L; 1111 1161;;;;N;CIRCLED HANGUL PA;;;; 327B;CIRCLED HANGUL HIEUH A;So;0;L; 1112 1161;;;;N;CIRCLED HANGUL HA;;;; 327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON; 110E 1161 11B7 1100 1169;;;;N;;;;; 327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON; 110C 116E 110B 1174;;;;N;;;;; 327E;CIRCLED HANGUL IEUNG U;So;0;ON; 110B 116E;;;;N;;;;; 327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; 3280;CIRCLED IDEOGRAPH ONE;No;0;L; 4E00;;;1;N;;;;; 3281;CIRCLED IDEOGRAPH TWO;No;0;L; 4E8C;;;2;N;;;;; 3282;CIRCLED IDEOGRAPH THREE;No;0;L; 4E09;;;3;N;;;;; 3283;CIRCLED IDEOGRAPH FOUR;No;0;L; 56DB;;;4;N;;;;; 3284;CIRCLED IDEOGRAPH FIVE;No;0;L; 4E94;;;5;N;;;;; 3285;CIRCLED IDEOGRAPH SIX;No;0;L; 516D;;;6;N;;;;; 3286;CIRCLED IDEOGRAPH SEVEN;No;0;L; 4E03;;;7;N;;;;; 3287;CIRCLED IDEOGRAPH EIGHT;No;0;L; 516B;;;8;N;;;;; 3288;CIRCLED IDEOGRAPH NINE;No;0;L; 4E5D;;;9;N;;;;; 3289;CIRCLED IDEOGRAPH TEN;No;0;L; 5341;;;10;N;;;;; 328A;CIRCLED IDEOGRAPH MOON;So;0;L; 6708;;;;N;;;;; 328B;CIRCLED IDEOGRAPH FIRE;So;0;L; 706B;;;;N;;;;; 328C;CIRCLED IDEOGRAPH WATER;So;0;L; 6C34;;;;N;;;;; 328D;CIRCLED IDEOGRAPH WOOD;So;0;L; 6728;;;;N;;;;; 328E;CIRCLED IDEOGRAPH METAL;So;0;L; 91D1;;;;N;;;;; 328F;CIRCLED IDEOGRAPH EARTH;So;0;L; 571F;;;;N;;;;; 3290;CIRCLED IDEOGRAPH SUN;So;0;L; 65E5;;;;N;;;;; 3291;CIRCLED IDEOGRAPH STOCK;So;0;L; 682A;;;;N;;;;; 3292;CIRCLED IDEOGRAPH HAVE;So;0;L; 6709;;;;N;;;;; 3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L; 793E;;;;N;;;;; 3294;CIRCLED IDEOGRAPH NAME;So;0;L; 540D;;;;N;;;;; 3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L; 7279;;;;N;;;;; 3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L; 8CA1;;;;N;;;;; 3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L; 795D;;;;N;;;;; 3298;CIRCLED IDEOGRAPH LABOR;So;0;L; 52B4;;;;N;;;;; 3299;CIRCLED IDEOGRAPH SECRET;So;0;L; 79D8;;;;N;;;;; 329A;CIRCLED IDEOGRAPH MALE;So;0;L; 7537;;;;N;;;;; 329B;CIRCLED IDEOGRAPH FEMALE;So;0;L; 5973;;;;N;;;;; 329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L; 9069;;;;N;;;;; 329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L; 512A;;;;N;;;;; 329E;CIRCLED IDEOGRAPH PRINT;So;0;L; 5370;;;;N;;;;; 329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L; 6CE8;;;;N;;;;; 32A0;CIRCLED IDEOGRAPH ITEM;So;0;L; 9805;;;;N;;;;; 32A1;CIRCLED IDEOGRAPH REST;So;0;L; 4F11;;;;N;;;;; 32A2;CIRCLED IDEOGRAPH COPY;So;0;L; 5199;;;;N;;;;; 32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L; 6B63;;;;N;;;;; 32A4;CIRCLED IDEOGRAPH HIGH;So;0;L; 4E0A;;;;N;;;;; 32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L; 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; 32A6;CIRCLED IDEOGRAPH LOW;So;0;L; 4E0B;;;;N;;;;; 32A7;CIRCLED IDEOGRAPH LEFT;So;0;L; 5DE6;;;;N;;;;; 32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L; 53F3;;;;N;;;;; 32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L; 533B;;;;N;;;;; 32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L; 5B97;;;;N;;;;; 32AB;CIRCLED IDEOGRAPH STUDY;So;0;L; 5B66;;;;N;;;;; 32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L; 76E3;;;;N;;;;; 32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L; 4F01;;;;N;;;;; 32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L; 8CC7;;;;N;;;;; 32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L; 5354;;;;N;;;;; 32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L; 591C;;;;N;;;;; 32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON; 0033 0036;;;36;N;;;;; 32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON; 0033 0037;;;37;N;;;;; 32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON; 0033 0038;;;38;N;;;;; 32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON; 0033 0039;;;39;N;;;;; 32B5;CIRCLED NUMBER FORTY;No;0;ON; 0034 0030;;;40;N;;;;; 32B6;CIRCLED NUMBER FORTY ONE;No;0;ON; 0034 0031;;;41;N;;;;; 32B7;CIRCLED NUMBER FORTY TWO;No;0;ON; 0034 0032;;;42;N;;;;; 32B8;CIRCLED NUMBER FORTY THREE;No;0;ON; 0034 0033;;;43;N;;;;; 32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON; 0034 0034;;;44;N;;;;; 32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON; 0034 0035;;;45;N;;;;; 32BB;CIRCLED NUMBER FORTY SIX;No;0;ON; 0034 0036;;;46;N;;;;; 32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON; 0034 0037;;;47;N;;;;; 32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON; 0034 0038;;;48;N;;;;; 32BE;CIRCLED NUMBER FORTY NINE;No;0;ON; 0034 0039;;;49;N;;;;; 32BF;CIRCLED NUMBER FIFTY;No;0;ON; 0035 0030;;;50;N;;;;; 32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L; 0031 6708;;;;N;;;;; 32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L; 0032 6708;;;;N;;;;; 32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L; 0033 6708;;;;N;;;;; 32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L; 0034 6708;;;;N;;;;; 32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L; 0035 6708;;;;N;;;;; 32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L; 0036 6708;;;;N;;;;; 32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L; 0037 6708;;;;N;;;;; 32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L; 0038 6708;;;;N;;;;; 32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L; 0039 6708;;;;N;;;;; 32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L; 0031 0030 6708;;;;N;;;;; 32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L; 0031 0031 6708;;;;N;;;;; 32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L; 0031 0032 6708;;;;N;;;;; 32CC;SQUARE HG;So;0;ON; 0048 0067;;;;N;;;;; 32CD;SQUARE ERG;So;0;ON; 0065 0072 0067;;;;N;;;;; 32CE;SQUARE EV;So;0;ON; 0065 0056;;;;N;;;;; 32CF;LIMITED LIABILITY SIGN;So;0;ON; 004C 0054 0044;;;;N;;;;; 32D0;CIRCLED KATAKANA A;So;0;L; 30A2;;;;N;;;;; 32D1;CIRCLED KATAKANA I;So;0;L; 30A4;;;;N;;;;; 32D2;CIRCLED KATAKANA U;So;0;L; 30A6;;;;N;;;;; 32D3;CIRCLED KATAKANA E;So;0;L; 30A8;;;;N;;;;; 32D4;CIRCLED KATAKANA O;So;0;L; 30AA;;;;N;;;;; 32D5;CIRCLED KATAKANA KA;So;0;L; 30AB;;;;N;;;;; 32D6;CIRCLED KATAKANA KI;So;0;L; 30AD;;;;N;;;;; 32D7;CIRCLED KATAKANA KU;So;0;L; 30AF;;;;N;;;;; 32D8;CIRCLED KATAKANA KE;So;0;L; 30B1;;;;N;;;;; 32D9;CIRCLED KATAKANA KO;So;0;L; 30B3;;;;N;;;;; 32DA;CIRCLED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; 32DB;CIRCLED KATAKANA SI;So;0;L; 30B7;;;;N;;;;; 32DC;CIRCLED KATAKANA SU;So;0;L; 30B9;;;;N;;;;; 32DD;CIRCLED KATAKANA SE;So;0;L; 30BB;;;;N;;;;; 32DE;CIRCLED KATAKANA SO;So;0;L; 30BD;;;;N;;;;; 32DF;CIRCLED KATAKANA TA;So;0;L; 30BF;;;;N;;;;; 32E0;CIRCLED KATAKANA TI;So;0;L; 30C1;;;;N;;;;; 32E1;CIRCLED KATAKANA TU;So;0;L; 30C4;;;;N;;;;; 32E2;CIRCLED KATAKANA TE;So;0;L; 30C6;;;;N;;;;; 32E3;CIRCLED KATAKANA TO;So;0;L; 30C8;;;;N;;;;; 32E4;CIRCLED KATAKANA NA;So;0;L; 30CA;;;;N;;;;; 32E5;CIRCLED KATAKANA NI;So;0;L; 30CB;;;;N;;;;; 32E6;CIRCLED KATAKANA NU;So;0;L; 30CC;;;;N;;;;; 32E7;CIRCLED KATAKANA NE;So;0;L; 30CD;;;;N;;;;; 32E8;CIRCLED KATAKANA NO;So;0;L; 30CE;;;;N;;;;; 32E9;CIRCLED KATAKANA HA;So;0;L; 30CF;;;;N;;;;; 32EA;CIRCLED KATAKANA HI;So;0;L; 30D2;;;;N;;;;; 32EB;CIRCLED KATAKANA HU;So;0;L; 30D5;;;;N;;;;; 32EC;CIRCLED KATAKANA HE;So;0;L; 30D8;;;;N;;;;; 32ED;CIRCLED KATAKANA HO;So;0;L; 30DB;;;;N;;;;; 32EE;CIRCLED KATAKANA MA;So;0;L; 30DE;;;;N;;;;; 32EF;CIRCLED KATAKANA MI;So;0;L; 30DF;;;;N;;;;; 32F0;CIRCLED KATAKANA MU;So;0;L; 30E0;;;;N;;;;; 32F1;CIRCLED KATAKANA ME;So;0;L; 30E1;;;;N;;;;; 32F2;CIRCLED KATAKANA MO;So;0;L; 30E2;;;;N;;;;; 32F3;CIRCLED KATAKANA YA;So;0;L; 30E4;;;;N;;;;; 32F4;CIRCLED KATAKANA YU;So;0;L; 30E6;;;;N;;;;; 32F5;CIRCLED KATAKANA YO;So;0;L; 30E8;;;;N;;;;; 32F6;CIRCLED KATAKANA RA;So;0;L; 30E9;;;;N;;;;; 32F7;CIRCLED KATAKANA RI;So;0;L; 30EA;;;;N;;;;; 32F8;CIRCLED KATAKANA RU;So;0;L; 30EB;;;;N;;;;; 32F9;CIRCLED KATAKANA RE;So;0;L; 30EC;;;;N;;;;; 32FA;CIRCLED KATAKANA RO;So;0;L; 30ED;;;;N;;;;; 32FB;CIRCLED KATAKANA WA;So;0;L; 30EF;;;;N;;;;; 32FC;CIRCLED KATAKANA WI;So;0;L; 30F0;;;;N;;;;; 32FD;CIRCLED KATAKANA WE;So;0;L; 30F1;;;;N;;;;; 32FE;CIRCLED KATAKANA WO;So;0;L; 30F2;;;;N;;;;; 3300;SQUARE APAATO;So;0;L; 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; 3301;SQUARE ARUHUA;So;0;L; 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; 3302;SQUARE ANPEA;So;0;L; 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; 3303;SQUARE AARU;So;0;L; 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; 3304;SQUARE ININGU;So;0;L; 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; 3305;SQUARE INTI;So;0;L; 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; 3306;SQUARE UON;So;0;L; 30A6 30A9 30F3;;;;N;SQUARED UON;;;; 3307;SQUARE ESUKUUDO;So;0;L; 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; 3308;SQUARE EEKAA;So;0;L; 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; 3309;SQUARE ONSU;So;0;L; 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; 330A;SQUARE OOMU;So;0;L; 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; 330B;SQUARE KAIRI;So;0;L; 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; 330C;SQUARE KARATTO;So;0;L; 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; 330D;SQUARE KARORII;So;0;L; 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; 330E;SQUARE GARON;So;0;L; 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; 330F;SQUARE GANMA;So;0;L; 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; 3310;SQUARE GIGA;So;0;L; 30AE 30AC;;;;N;SQUARED GIGA;;;; 3311;SQUARE GINII;So;0;L; 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; 3312;SQUARE KYURII;So;0;L; 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; 3313;SQUARE GIRUDAA;So;0;L; 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; 3314;SQUARE KIRO;So;0;L; 30AD 30ED;;;;N;SQUARED KIRO;;;; 3315;SQUARE KIROGURAMU;So;0;L; 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; 3316;SQUARE KIROMEETORU;So;0;L; 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; 3317;SQUARE KIROWATTO;So;0;L; 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; 3318;SQUARE GURAMU;So;0;L; 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; 3319;SQUARE GURAMUTON;So;0;L; 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; 331A;SQUARE KURUZEIRO;So;0;L; 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; 331B;SQUARE KUROONE;So;0;L; 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; 331C;SQUARE KEESU;So;0;L; 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; 331D;SQUARE KORUNA;So;0;L; 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; 331E;SQUARE KOOPO;So;0;L; 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; 331F;SQUARE SAIKURU;So;0;L; 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; 3320;SQUARE SANTIIMU;So;0;L; 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; 3321;SQUARE SIRINGU;So;0;L; 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; 3322;SQUARE SENTI;So;0;L; 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; 3323;SQUARE SENTO;So;0;L; 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; 3324;SQUARE DAASU;So;0;L; 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; 3325;SQUARE DESI;So;0;L; 30C7 30B7;;;;N;SQUARED DESI;;;; 3326;SQUARE DORU;So;0;L; 30C9 30EB;;;;N;SQUARED DORU;;;; 3327;SQUARE TON;So;0;L; 30C8 30F3;;;;N;SQUARED TON;;;; 3328;SQUARE NANO;So;0;L; 30CA 30CE;;;;N;SQUARED NANO;;;; 3329;SQUARE NOTTO;So;0;L; 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; 332A;SQUARE HAITU;So;0;L; 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; 332B;SQUARE PAASENTO;So;0;L; 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; 332C;SQUARE PAATU;So;0;L; 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; 332D;SQUARE BAARERU;So;0;L; 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; 332E;SQUARE PIASUTORU;So;0;L; 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; 332F;SQUARE PIKURU;So;0;L; 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; 3330;SQUARE PIKO;So;0;L; 30D4 30B3;;;;N;SQUARED PIKO;;;; 3331;SQUARE BIRU;So;0;L; 30D3 30EB;;;;N;SQUARED BIRU;;;; 3332;SQUARE HUARADDO;So;0;L; 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; 3333;SQUARE HUIITO;So;0;L; 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; 3334;SQUARE BUSSYERU;So;0;L; 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; 3335;SQUARE HURAN;So;0;L; 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; 3336;SQUARE HEKUTAARU;So;0;L; 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; 3337;SQUARE PESO;So;0;L; 30DA 30BD;;;;N;SQUARED PESO;;;; 3338;SQUARE PENIHI;So;0;L; 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; 3339;SQUARE HERUTU;So;0;L; 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; 333A;SQUARE PENSU;So;0;L; 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; 333B;SQUARE PEEZI;So;0;L; 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; 333C;SQUARE BEETA;So;0;L; 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; 333D;SQUARE POINTO;So;0;L; 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; 333E;SQUARE BORUTO;So;0;L; 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; 333F;SQUARE HON;So;0;L; 30DB 30F3;;;;N;SQUARED HON;;;; 3340;SQUARE PONDO;So;0;L; 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; 3341;SQUARE HOORU;So;0;L; 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; 3342;SQUARE HOON;So;0;L; 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; 3343;SQUARE MAIKURO;So;0;L; 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; 3344;SQUARE MAIRU;So;0;L; 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; 3345;SQUARE MAHHA;So;0;L; 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; 3346;SQUARE MARUKU;So;0;L; 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; 3347;SQUARE MANSYON;So;0;L; 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; 3348;SQUARE MIKURON;So;0;L; 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; 3349;SQUARE MIRI;So;0;L; 30DF 30EA;;;;N;SQUARED MIRI;;;; 334A;SQUARE MIRIBAARU;So;0;L; 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; 334B;SQUARE MEGA;So;0;L; 30E1 30AC;;;;N;SQUARED MEGA;;;; 334C;SQUARE MEGATON;So;0;L; 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; 334D;SQUARE MEETORU;So;0;L; 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; 334E;SQUARE YAADO;So;0;L; 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; 334F;SQUARE YAARU;So;0;L; 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; 3350;SQUARE YUAN;So;0;L; 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; 3351;SQUARE RITTORU;So;0;L; 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; 3352;SQUARE RIRA;So;0;L; 30EA 30E9;;;;N;SQUARED RIRA;;;; 3353;SQUARE RUPII;So;0;L; 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; 3354;SQUARE RUUBURU;So;0;L; 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; 3355;SQUARE REMU;So;0;L; 30EC 30E0;;;;N;SQUARED REMU;;;; 3356;SQUARE RENTOGEN;So;0;L; 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; 3357;SQUARE WATTO;So;0;L; 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; 3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L; 0030 70B9;;;;N;;;;; 3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L; 0031 70B9;;;;N;;;;; 335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L; 0032 70B9;;;;N;;;;; 335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L; 0033 70B9;;;;N;;;;; 335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L; 0034 70B9;;;;N;;;;; 335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L; 0035 70B9;;;;N;;;;; 335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L; 0036 70B9;;;;N;;;;; 335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L; 0037 70B9;;;;N;;;;; 3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L; 0038 70B9;;;;N;;;;; 3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L; 0039 70B9;;;;N;;;;; 3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L; 0031 0030 70B9;;;;N;;;;; 3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L; 0031 0031 70B9;;;;N;;;;; 3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L; 0031 0032 70B9;;;;N;;;;; 3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L; 0031 0033 70B9;;;;N;;;;; 3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L; 0031 0034 70B9;;;;N;;;;; 3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L; 0031 0035 70B9;;;;N;;;;; 3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L; 0031 0036 70B9;;;;N;;;;; 3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L; 0031 0037 70B9;;;;N;;;;; 336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L; 0031 0038 70B9;;;;N;;;;; 336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L; 0031 0039 70B9;;;;N;;;;; 336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L; 0032 0030 70B9;;;;N;;;;; 336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L; 0032 0031 70B9;;;;N;;;;; 336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L; 0032 0032 70B9;;;;N;;;;; 336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L; 0032 0033 70B9;;;;N;;;;; 3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L; 0032 0034 70B9;;;;N;;;;; 3371;SQUARE HPA;So;0;L; 0068 0050 0061;;;;N;;;;; 3372;SQUARE DA;So;0;L; 0064 0061;;;;N;;;;; 3373;SQUARE AU;So;0;L; 0041 0055;;;;N;;;;; 3374;SQUARE BAR;So;0;L; 0062 0061 0072;;;;N;;;;; 3375;SQUARE OV;So;0;L; 006F 0056;;;;N;;;;; 3376;SQUARE PC;So;0;L; 0070 0063;;;;N;;;;; 3377;SQUARE DM;So;0;ON; 0064 006D;;;;N;;;;; 3378;SQUARE DM SQUARED;So;0;ON; 0064 006D 00B2;;;;N;;;;; 3379;SQUARE DM CUBED;So;0;ON; 0064 006D 00B3;;;;N;;;;; 337A;SQUARE IU;So;0;ON; 0049 0055;;;;N;;;;; 337B;SQUARE ERA NAME HEISEI;So;0;L; 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; 337C;SQUARE ERA NAME SYOUWA;So;0;L; 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; 337D;SQUARE ERA NAME TAISYOU;So;0;L; 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; 337E;SQUARE ERA NAME MEIZI;So;0;L; 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; 337F;SQUARE CORPORATION;So;0;L; 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; 3380;SQUARE PA AMPS;So;0;L; 0070 0041;;;;N;SQUARED PA AMPS;;;; 3381;SQUARE NA;So;0;L; 006E 0041;;;;N;SQUARED NA;;;; 3382;SQUARE MU A;So;0;L; 03BC 0041;;;;N;SQUARED MU A;;;; 3383;SQUARE MA;So;0;L; 006D 0041;;;;N;SQUARED MA;;;; 3384;SQUARE KA;So;0;L; 006B 0041;;;;N;SQUARED KA;;;; 3385;SQUARE KB;So;0;L; 004B 0042;;;;N;SQUARED KB;;;; 3386;SQUARE MB;So;0;L; 004D 0042;;;;N;SQUARED MB;;;; 3387;SQUARE GB;So;0;L; 0047 0042;;;;N;SQUARED GB;;;; 3388;SQUARE CAL;So;0;L; 0063 0061 006C;;;;N;SQUARED CAL;;;; 3389;SQUARE KCAL;So;0;L; 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; 338A;SQUARE PF;So;0;L; 0070 0046;;;;N;SQUARED PF;;;; 338B;SQUARE NF;So;0;L; 006E 0046;;;;N;SQUARED NF;;;; 338C;SQUARE MU F;So;0;L; 03BC 0046;;;;N;SQUARED MU F;;;; 338D;SQUARE MU G;So;0;L; 03BC 0067;;;;N;SQUARED MU G;;;; 338E;SQUARE MG;So;0;L; 006D 0067;;;;N;SQUARED MG;;;; 338F;SQUARE KG;So;0;L; 006B 0067;;;;N;SQUARED KG;;;; 3390;SQUARE HZ;So;0;L; 0048 007A;;;;N;SQUARED HZ;;;; 3391;SQUARE KHZ;So;0;L; 006B 0048 007A;;;;N;SQUARED KHZ;;;; 3392;SQUARE MHZ;So;0;L; 004D 0048 007A;;;;N;SQUARED MHZ;;;; 3393;SQUARE GHZ;So;0;L; 0047 0048 007A;;;;N;SQUARED GHZ;;;; 3394;SQUARE THZ;So;0;L; 0054 0048 007A;;;;N;SQUARED THZ;;;; 3395;SQUARE MU L;So;0;L; 03BC 2113;;;;N;SQUARED MU L;;;; 3396;SQUARE ML;So;0;L; 006D 2113;;;;N;SQUARED ML;;;; 3397;SQUARE DL;So;0;L; 0064 2113;;;;N;SQUARED DL;;;; 3398;SQUARE KL;So;0;L; 006B 2113;;;;N;SQUARED KL;;;; 3399;SQUARE FM;So;0;L; 0066 006D;;;;N;SQUARED FM;;;; 339A;SQUARE NM;So;0;L; 006E 006D;;;;N;SQUARED NM;;;; 339B;SQUARE MU M;So;0;L; 03BC 006D;;;;N;SQUARED MU M;;;; 339C;SQUARE MM;So;0;L; 006D 006D;;;;N;SQUARED MM;;;; 339D;SQUARE CM;So;0;L; 0063 006D;;;;N;SQUARED CM;;;; 339E;SQUARE KM;So;0;L; 006B 006D;;;;N;SQUARED KM;;;; 339F;SQUARE MM SQUARED;So;0;L; 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; 33A0;SQUARE CM SQUARED;So;0;L; 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; 33A1;SQUARE M SQUARED;So;0;L; 006D 00B2;;;;N;SQUARED M SQUARED;;;; 33A2;SQUARE KM SQUARED;So;0;L; 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; 33A3;SQUARE MM CUBED;So;0;L; 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; 33A4;SQUARE CM CUBED;So;0;L; 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; 33A5;SQUARE M CUBED;So;0;L; 006D 00B3;;;;N;SQUARED M CUBED;;;; 33A6;SQUARE KM CUBED;So;0;L; 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; 33A7;SQUARE M OVER S;So;0;L; 006D 2215 0073;;;;N;SQUARED M OVER S;;;; 33A8;SQUARE M OVER S SQUARED;So;0;L; 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; 33A9;SQUARE PA;So;0;L; 0050 0061;;;;N;SQUARED PA;;;; 33AA;SQUARE KPA;So;0;L; 006B 0050 0061;;;;N;SQUARED KPA;;;; 33AB;SQUARE MPA;So;0;L; 004D 0050 0061;;;;N;SQUARED MPA;;;; 33AC;SQUARE GPA;So;0;L; 0047 0050 0061;;;;N;SQUARED GPA;;;; 33AD;SQUARE RAD;So;0;L; 0072 0061 0064;;;;N;SQUARED RAD;;;; 33AE;SQUARE RAD OVER S;So;0;L; 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; 33AF;SQUARE RAD OVER S SQUARED;So;0;L; 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; 33B0;SQUARE PS;So;0;L; 0070 0073;;;;N;SQUARED PS;;;; 33B1;SQUARE NS;So;0;L; 006E 0073;;;;N;SQUARED NS;;;; 33B2;SQUARE MU S;So;0;L; 03BC 0073;;;;N;SQUARED MU S;;;; 33B3;SQUARE MS;So;0;L; 006D 0073;;;;N;SQUARED MS;;;; 33B4;SQUARE PV;So;0;L; 0070 0056;;;;N;SQUARED PV;;;; 33B5;SQUARE NV;So;0;L; 006E 0056;;;;N;SQUARED NV;;;; 33B6;SQUARE MU V;So;0;L; 03BC 0056;;;;N;SQUARED MU V;;;; 33B7;SQUARE MV;So;0;L; 006D 0056;;;;N;SQUARED MV;;;; 33B8;SQUARE KV;So;0;L; 006B 0056;;;;N;SQUARED KV;;;; 33B9;SQUARE MV MEGA;So;0;L; 004D 0056;;;;N;SQUARED MV MEGA;;;; 33BA;SQUARE PW;So;0;L; 0070 0057;;;;N;SQUARED PW;;;; 33BB;SQUARE NW;So;0;L; 006E 0057;;;;N;SQUARED NW;;;; 33BC;SQUARE MU W;So;0;L; 03BC 0057;;;;N;SQUARED MU W;;;; 33BD;SQUARE MW;So;0;L; 006D 0057;;;;N;SQUARED MW;;;; 33BE;SQUARE KW;So;0;L; 006B 0057;;;;N;SQUARED KW;;;; 33BF;SQUARE MW MEGA;So;0;L; 004D 0057;;;;N;SQUARED MW MEGA;;;; 33C0;SQUARE K OHM;So;0;L; 006B 03A9;;;;N;SQUARED K OHM;;;; 33C1;SQUARE M OHM;So;0;L; 004D 03A9;;;;N;SQUARED M OHM;;;; 33C2;SQUARE AM;So;0;L; 0061 002E 006D 002E;;;;N;SQUARED AM;;;; 33C3;SQUARE BQ;So;0;L; 0042 0071;;;;N;SQUARED BQ;;;; 33C4;SQUARE CC;So;0;L; 0063 0063;;;;N;SQUARED CC;;;; 33C5;SQUARE CD;So;0;L; 0063 0064;;;;N;SQUARED CD;;;; 33C6;SQUARE C OVER KG;So;0;L; 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; 33C7;SQUARE CO;So;0;L; 0043 006F 002E;;;;N;SQUARED CO;;;; 33C8;SQUARE DB;So;0;L; 0064 0042;;;;N;SQUARED DB;;;; 33C9;SQUARE GY;So;0;L; 0047 0079;;;;N;SQUARED GY;;;; 33CA;SQUARE HA;So;0;L; 0068 0061;;;;N;SQUARED HA;;;; 33CB;SQUARE HP;So;0;L; 0048 0050;;;;N;SQUARED HP;;;; 33CC;SQUARE IN;So;0;L; 0069 006E;;;;N;SQUARED IN;;;; 33CD;SQUARE KK;So;0;L; 004B 004B;;;;N;SQUARED KK;;;; 33CE;SQUARE KM CAPITAL;So;0;L; 004B 004D;;;;N;SQUARED KM CAPITAL;;;; 33CF;SQUARE KT;So;0;L; 006B 0074;;;;N;SQUARED KT;;;; 33D0;SQUARE LM;So;0;L; 006C 006D;;;;N;SQUARED LM;;;; 33D1;SQUARE LN;So;0;L; 006C 006E;;;;N;SQUARED LN;;;; 33D2;SQUARE LOG;So;0;L; 006C 006F 0067;;;;N;SQUARED LOG;;;; 33D3;SQUARE LX;So;0;L; 006C 0078;;;;N;SQUARED LX;;;; 33D4;SQUARE MB SMALL;So;0;L; 006D 0062;;;;N;SQUARED MB SMALL;;;; 33D5;SQUARE MIL;So;0;L; 006D 0069 006C;;;;N;SQUARED MIL;;;; 33D6;SQUARE MOL;So;0;L; 006D 006F 006C;;;;N;SQUARED MOL;;;; 33D7;SQUARE PH;So;0;L; 0050 0048;;;;N;SQUARED PH;;;; 33D8;SQUARE PM;So;0;L; 0070 002E 006D 002E;;;;N;SQUARED PM;;;; 33D9;SQUARE PPM;So;0;L; 0050 0050 004D;;;;N;SQUARED PPM;;;; 33DA;SQUARE PR;So;0;L; 0050 0052;;;;N;SQUARED PR;;;; 33DB;SQUARE SR;So;0;L; 0073 0072;;;;N;SQUARED SR;;;; 33DC;SQUARE SV;So;0;L; 0053 0076;;;;N;SQUARED SV;;;; 33DD;SQUARE WB;So;0;L; 0057 0062;;;;N;SQUARED WB;;;; 33DE;SQUARE V OVER M;So;0;ON; 0056 2215 006D;;;;N;;;;; 33DF;SQUARE A OVER M;So;0;ON; 0041 2215 006D;;;;N;;;;; 33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L; 0031 65E5;;;;N;;;;; 33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L; 0032 65E5;;;;N;;;;; 33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L; 0033 65E5;;;;N;;;;; 33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L; 0034 65E5;;;;N;;;;; 33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L; 0035 65E5;;;;N;;;;; 33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L; 0036 65E5;;;;N;;;;; 33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L; 0037 65E5;;;;N;;;;; 33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L; 0038 65E5;;;;N;;;;; 33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L; 0039 65E5;;;;N;;;;; 33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L; 0031 0030 65E5;;;;N;;;;; 33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L; 0031 0031 65E5;;;;N;;;;; 33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L; 0031 0032 65E5;;;;N;;;;; 33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L; 0031 0033 65E5;;;;N;;;;; 33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L; 0031 0034 65E5;;;;N;;;;; 33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L; 0031 0035 65E5;;;;N;;;;; 33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L; 0031 0036 65E5;;;;N;;;;; 33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L; 0031 0037 65E5;;;;N;;;;; 33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L; 0031 0038 65E5;;;;N;;;;; 33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L; 0031 0039 65E5;;;;N;;;;; 33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L; 0032 0030 65E5;;;;N;;;;; 33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L; 0032 0031 65E5;;;;N;;;;; 33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L; 0032 0032 65E5;;;;N;;;;; 33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L; 0032 0033 65E5;;;;N;;;;; 33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L; 0032 0034 65E5;;;;N;;;;; 33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L; 0032 0035 65E5;;;;N;;;;; 33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L; 0032 0036 65E5;;;;N;;;;; 33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L; 0032 0037 65E5;;;;N;;;;; 33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L; 0032 0038 65E5;;;;N;;;;; 33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L; 0032 0039 65E5;;;;N;;;;; 33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L; 0033 0030 65E5;;;;N;;;;; 33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L; 0033 0031 65E5;;;;N;;;;; 33FF;SQUARE GAL;So;0;ON; 0067 0061 006C;;;;N;;;;; 3400;;Lo;0;L;;;;;N;;;;; 4DB5;;Lo;0;L;;;;;N;;;;; 4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;; 4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;; 4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;; 4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;; 4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;; 4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;; 4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;; 4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;; 4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;; 4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;; 4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;; 4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;; 4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;; 4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;; 4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;; 4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;; 4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;; 4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;; 4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;; 4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;; 4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;; 4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;; 4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;; 4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;; 4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;; 4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;; 4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;; 4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;; 4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;; 4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;; 4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;; 4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;; 4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;; 4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;; 4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;; 4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;; 4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;; 4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;; 4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;; 4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;; 4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;; 4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;; 4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;; 4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;; 4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;; 4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;; 4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;; 4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;; 4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;; 4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;; 4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;; 4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;; 4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;; 4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;; 4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;; 4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;; 4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;;Lo;0;L;;;;;N;;;;; 9FCC;;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;; A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;; A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;; A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;; A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;; A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;; A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;; A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;; A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;; A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;; A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;; A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;; A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;; A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;; A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;; A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;; A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;; A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;; A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;; A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;; A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;; A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;; A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;; A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;; A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;; A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;; A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;; A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;; A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;; A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;; A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;; A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;; A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;; A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;; A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;; A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;; A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;; A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;; A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;; A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;; A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;; A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;; A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;; A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;; A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;; A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;; A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;; A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;; A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;; A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;; A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;; A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;; A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;; A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;; A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;; A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;; A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;; A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;; A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;; A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;; A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;; A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;; A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;; A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;; A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;; A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;; A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;; A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;; A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;; A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;; A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;; A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;; A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;; A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;; A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;; A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;; A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;; A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;; A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;; A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;; A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;; A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;; A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;; A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;; A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;; A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;; A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;; A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;; A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;; A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;; A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;; A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;; A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;; A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;; A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;; A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;; A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;; A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;; A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;; A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;; A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;; A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;; A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;; A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;; A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;; A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;; A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;; A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;; A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;; A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;; A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;; A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;; A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;; A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;; A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;; A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;; A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;; A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;; A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;; A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;; A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;; A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;; A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;; A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;; A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;; A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;; A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;; A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;; A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;; A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;; A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;; A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;; A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;; A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;; A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;; A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;; A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;; A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;; A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;; A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;; A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;; A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;; A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;; A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;; A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;; A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;; A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;; A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;; A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;; A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;; A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;; A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;; A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;; A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;; A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;; A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;; A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;; A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;; A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;; A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;; A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;; A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;; A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;; A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;; A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;; A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;; A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;; A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;; A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;; A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;; A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;; A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;; A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;; A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;; A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;; A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;; A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;; A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;; A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;; A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;; A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;; A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;; A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;; A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;; A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;; A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;; A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;; A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;; A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;; A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;; A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;; A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;; A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;; A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;; A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;; A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;; A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;; A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;; A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;; A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;; A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;; A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;; A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;; A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;; A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;; A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;; A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;; A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;; A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;; A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;; A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; A60D;VAI COMMA;Po;0;ON;;;;;N;;;;; A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;; A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;; A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;; A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;; A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;; A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;; A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;; A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;; A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;; A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;; A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;; A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;; A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;; A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;; A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;; A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;; A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;; A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;; A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;; A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;; A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643; A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642 A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645; A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644 A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647; A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646 A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649; A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648 A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B; A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D; A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651; A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650 A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653; A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652 A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655; A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654 A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657; A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656 A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659; A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658 A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B; A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661; A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660 A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664 A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667; A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666 A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669; A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668 A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B; A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D; A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;; A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;; A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;; A674;COMBINING CYRILLIC LETTER UKRAINIAN IE;Mn;230;NSM;;;;;N;;;;; A675;COMBINING CYRILLIC LETTER I;Mn;230;NSM;;;;;N;;;;; A676;COMBINING CYRILLIC LETTER YI;Mn;230;NSM;;;;;N;;;;; A677;COMBINING CYRILLIC LETTER U;Mn;230;NSM;;;;;N;;;;; A678;COMBINING CYRILLIC LETTER HARD SIGN;Mn;230;NSM;;;;;N;;;;; A679;COMBINING CYRILLIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; A67A;COMBINING CYRILLIC LETTER SOFT SIGN;Mn;230;NSM;;;;;N;;;;; A67B;COMBINING CYRILLIC LETTER OMEGA;Mn;230;NSM;;;;;N;;;;; A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;; A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;; A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;; A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;; A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681; A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680 A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683; A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682 A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685; A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684 A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687; A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686 A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689; A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688 A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B; A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D; A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F; A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691; A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690 A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693; A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692 A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695; A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694 A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697; A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696 A698;CYRILLIC CAPITAL LETTER DOUBLE O;Lu;0;L;;;;;N;;;;A699; A699;CYRILLIC SMALL LETTER DOUBLE O;Ll;0;L;;;;;N;;;A698;;A698 A69A;CYRILLIC CAPITAL LETTER CROSSED O;Lu;0;L;;;;;N;;;;A69B; A69B;CYRILLIC SMALL LETTER CROSSED O;Ll;0;L;;;;;N;;;A69A;;A69A A69C;MODIFIER LETTER CYRILLIC HARD SIGN;Lm;0;L; 044A;;;;N;;;;; A69D;MODIFIER LETTER CYRILLIC SOFT SIGN;Lm;0;L; 044C;;;;N;;;;; A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;; A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;; A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;; A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;; A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;; A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;; A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;; A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;; A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;; A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;; A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;; A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;; A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;; A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;; A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;; A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;; A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;; A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;; A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;; A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;; A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;; A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;; A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;; A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;; A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;; A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;; A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;; A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;; A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;; A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;; A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;; A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;; A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;; A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;; A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;; A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;; A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;; A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;; A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;; A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;; A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;; A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;; A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;; A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;; A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;; A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;; A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;; A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;; A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;; A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;; A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;; A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;; A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;; A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;; A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;; A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;; A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;; A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;; A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;; A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;; A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;; A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;; A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;; A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;; A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;; A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;; A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;; A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;; A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;; A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;; A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;; A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;; A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;; A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;; A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;; A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;; A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;; A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;; A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;; A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;; A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;; A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;; A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;; A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;; A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;; A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;; A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;; A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;; A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;; A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;; A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;; A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;; A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;; A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;; A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;; A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;; A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;; A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;; A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;; A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;; A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;; A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;; A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;; A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;; A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;; A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723; A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722 A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725; A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724 A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727; A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726 A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729; A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728 A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B; A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D; A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F; A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;; A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;; A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733; A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732 A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735; A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734 A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737; A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736 A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739; A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738 A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B; A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D; A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F; A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741; A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740 A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743; A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742 A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745; A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744 A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747; A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746 A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749; A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748 A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B; A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D; A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F; A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751; A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750 A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753; A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752 A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755; A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754 A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757; A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756 A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759; A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758 A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B; A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D; A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F; A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761; A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760 A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763; A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762 A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765; A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764 A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767; A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766 A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769; A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768 A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B; A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D; A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F; A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E A770;MODIFIER LETTER US;Lm;0;L; A76F;;;;N;;;;; A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;; A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;; A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;; A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;; A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;; A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;; A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;; A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;; A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A; A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779 A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C; A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79; A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F; A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781; A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780 A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783; A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782 A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785; A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784 A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787; A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786 A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;; A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265; A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;; A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791; A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790 A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793; A793;LATIN SMALL LETTER C WITH BAR;Ll;0;L;;;;;N;;;A792;;A792 A794;LATIN SMALL LETTER C WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; A795;LATIN SMALL LETTER H WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; A796;LATIN CAPITAL LETTER B WITH FLOURISH;Lu;0;L;;;;;N;;;;A797; A797;LATIN SMALL LETTER B WITH FLOURISH;Ll;0;L;;;;;N;;;A796;;A796 A798;LATIN CAPITAL LETTER F WITH STROKE;Lu;0;L;;;;;N;;;;A799; A799;LATIN SMALL LETTER F WITH STROKE;Ll;0;L;;;;;N;;;A798;;A798 A79A;LATIN CAPITAL LETTER VOLAPUK AE;Lu;0;L;;;;;N;;;;A79B; A79B;LATIN SMALL LETTER VOLAPUK AE;Ll;0;L;;;;;N;;;A79A;;A79A A79C;LATIN CAPITAL LETTER VOLAPUK OE;Lu;0;L;;;;;N;;;;A79D; A79D;LATIN SMALL LETTER VOLAPUK OE;Ll;0;L;;;;;N;;;A79C;;A79C A79E;LATIN CAPITAL LETTER VOLAPUK UE;Lu;0;L;;;;;N;;;;A79F; A79F;LATIN SMALL LETTER VOLAPUK UE;Ll;0;L;;;;;N;;;A79E;;A79E A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1; A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0 A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3; A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2 A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5; A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4 A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7; A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6 A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9; A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8 A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266; A7AB;LATIN CAPITAL LETTER REVERSED OPEN E;Lu;0;L;;;;;N;;;;025C; A7AC;LATIN CAPITAL LETTER SCRIPT G;Lu;0;L;;;;;N;;;;0261; A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C; A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E; A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287; A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;; A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L; 0126;;;;N;;;;; A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L; 0153;;;;N;;;;; A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;; A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;; A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;; A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;; A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;; A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;; A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;; A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;; A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;; A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;; A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;; A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;; A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;; A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;; A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;; A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;; A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;; A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;; A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;; A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;; A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;; A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;; A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;; A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;; A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;; A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;; A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;; A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;; A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;; A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;; A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;; A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;; A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;; A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;; A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;; A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;; A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;; A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;; A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;; A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;; A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;; A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;; A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;; A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;; A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;; A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;; A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;; A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;; A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;; A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;; A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;; A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;; A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;; A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;; A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;; A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;; A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;; A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;; A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;; A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;; A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;; A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;; A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;; A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;; A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;; A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;; A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;; A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;; A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;; A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;; A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;; A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;; A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;; A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;; A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;; A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;; A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;; A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;; A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;; A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;; A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;; A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;; A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;; A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;; A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;; A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;; A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;; A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;; A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;; A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;; A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;; A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;; A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;; A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;; A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;; A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;; A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;; A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;; A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;; A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;; A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;; A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;; A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;; A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;; A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;; A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;; A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;; A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;; A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;; A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;; A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;; A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;; A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;; A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;; A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;; A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;; A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;; A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;; A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;; A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;; A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;; A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;; A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;; A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;; A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;; A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;; A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;; A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;; A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;; A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;; A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;; A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;; A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;; A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;; A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;; A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;; A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;; A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;; A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;; A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;; A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;; A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;; A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;; A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;; A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;; A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;; A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;; A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;; A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;; A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;; A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;; A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;; A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;; A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;; A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;; A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;; A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;; A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;; A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;; A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;; A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;; A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;; A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;; A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;; A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;; A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;; A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;; A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;; A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;; A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;; A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;; A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;; A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;; A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;; A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;; A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;; A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;; A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;; A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;; A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;; A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;; A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;; A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;; A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;; A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;; A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;; A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;; A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;; A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;; A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;; A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;; A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;; A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;; A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;; A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;; A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;; A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;; A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;; A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;; A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;; A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;; A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;; A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;; A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;; A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;; A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;; A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;; A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;; A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;; A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;; A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;; A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;; A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;; A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;; A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;; A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;; A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;; A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;; A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;; A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;; A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;; A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;; A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;; A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;; A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;; A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;; A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;; A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;; A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;; A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;; A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;; A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;; A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;; A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;; A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;; A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;; A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;; A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;; A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;; A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;; A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;; A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;; A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;; A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;; A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;; A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;; A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;; A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;; A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;; A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;; A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;; A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;; A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;; A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;; A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;; A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;; A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;; A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;; A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;; A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;; A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;; A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;; A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;; A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;; A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;; A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;; A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;; A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;; A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;; A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;; A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;; A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;; A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;; A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;; A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;; A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;; A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;; A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;; A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;; A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;; A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;; A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;; A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;; A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;; A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;; A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;; A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;; A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;; A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;; A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;; A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;; A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;; A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;; A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;; A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;; A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;; A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;; A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;; A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;; A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;; A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;; A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;; A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;; A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;; A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;; A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;; A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;; A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;; A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;; A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;; A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;; A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;; A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;; A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;; A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;; A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;; A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;; A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;; A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;; A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;; A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;; A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;; A9E0;MYANMAR LETTER SHAN GHA;Lo;0;L;;;;;N;;;;; A9E1;MYANMAR LETTER SHAN CHA;Lo;0;L;;;;;N;;;;; A9E2;MYANMAR LETTER SHAN JHA;Lo;0;L;;;;;N;;;;; A9E3;MYANMAR LETTER SHAN NNA;Lo;0;L;;;;;N;;;;; A9E4;MYANMAR LETTER SHAN BHA;Lo;0;L;;;;;N;;;;; A9E5;MYANMAR SIGN SHAN SAW;Mn;0;NSM;;;;;N;;;;; A9E6;MYANMAR MODIFIER LETTER SHAN REDUPLICATION;Lm;0;L;;;;;N;;;;; A9E7;MYANMAR LETTER TAI LAING NYA;Lo;0;L;;;;;N;;;;; A9E8;MYANMAR LETTER TAI LAING FA;Lo;0;L;;;;;N;;;;; A9E9;MYANMAR LETTER TAI LAING GA;Lo;0;L;;;;;N;;;;; A9EA;MYANMAR LETTER TAI LAING GHA;Lo;0;L;;;;;N;;;;; A9EB;MYANMAR LETTER TAI LAING JA;Lo;0;L;;;;;N;;;;; A9EC;MYANMAR LETTER TAI LAING JHA;Lo;0;L;;;;;N;;;;; A9ED;MYANMAR LETTER TAI LAING DDA;Lo;0;L;;;;;N;;;;; A9EE;MYANMAR LETTER TAI LAING DDHA;Lo;0;L;;;;;N;;;;; A9EF;MYANMAR LETTER TAI LAING NNA;Lo;0;L;;;;;N;;;;; A9F0;MYANMAR TAI LAING DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A9F1;MYANMAR TAI LAING DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A9F2;MYANMAR TAI LAING DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A9F3;MYANMAR TAI LAING DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A9F4;MYANMAR TAI LAING DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A9F5;MYANMAR TAI LAING DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A9F6;MYANMAR TAI LAING DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A9F7;MYANMAR TAI LAING DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A9F8;MYANMAR TAI LAING DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A9F9;MYANMAR TAI LAING DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A9FA;MYANMAR LETTER TAI LAING LLA;Lo;0;L;;;;;N;;;;; A9FB;MYANMAR LETTER TAI LAING DA;Lo;0;L;;;;;N;;;;; A9FC;MYANMAR LETTER TAI LAING DHA;Lo;0;L;;;;;N;;;;; A9FD;MYANMAR LETTER TAI LAING BA;Lo;0;L;;;;;N;;;;; A9FE;MYANMAR LETTER TAI LAING BHA;Lo;0;L;;;;;N;;;;; AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;; AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;; AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;; AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;; AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;; AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;; AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;; AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;; AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;; AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;; AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;; AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;; AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;; AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;; AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;; AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;; AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;; AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;; AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;; AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;; AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;; AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;; AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;; AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;; AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;; AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;; AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;; AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;; AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;; AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;; AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;; AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;; AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;; AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;; AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;; AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;; AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;; AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;; AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;; AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;; AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;; AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;; AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;; AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;; AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;; AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;; AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;; AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;; AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;; AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;; AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;; AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;; AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;; AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;; AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;; AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;; AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;; AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;; AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;; AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;; AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;; AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;; AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;; AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;; AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;; AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;; AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;; AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;; AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;; AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;; AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;; AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;; AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;; AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;; AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;; AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;; AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;; AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;; AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;; AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;; AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;; AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;; AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;; AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;; AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;; AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;; AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;; AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;; AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;; AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;; AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;; AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;; AA7C;MYANMAR SIGN TAI LAING TONE-2;Mn;0;NSM;;;;;N;;;;; AA7D;MYANMAR SIGN TAI LAING TONE-5;Mc;0;L;;;;;N;;;;; AA7E;MYANMAR LETTER SHWE PALAUNG CHA;Lo;0;L;;;;;N;;;;; AA7F;MYANMAR LETTER SHWE PALAUNG SHA;Lo;0;L;;;;;N;;;;; AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;; AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;; AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;; AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;; AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;; AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;; AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;; AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;; AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;; AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;; AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;; AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;; AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;; AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;; AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;; AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;; AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;; AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;; AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;; AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;; AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;; AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;; AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;; AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;; AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;; AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;; AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;; AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;; AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;; AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;; AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;; AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;; AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;; AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;; AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;; AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;; AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;; AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;; AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;; AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;; AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;; AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;; AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;; AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;; AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;; AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;; AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;; AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;; AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;; AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;; AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;; AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;; AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;; AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;; AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;; AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;; AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;; AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;; AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;; AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;; AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;; AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;; AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;; AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;; AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;; AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;; AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; AAE0;MEETEI MAYEK LETTER E;Lo;0;L;;;;;N;;;;; AAE1;MEETEI MAYEK LETTER O;Lo;0;L;;;;;N;;;;; AAE2;MEETEI MAYEK LETTER CHA;Lo;0;L;;;;;N;;;;; AAE3;MEETEI MAYEK LETTER NYA;Lo;0;L;;;;;N;;;;; AAE4;MEETEI MAYEK LETTER TTA;Lo;0;L;;;;;N;;;;; AAE5;MEETEI MAYEK LETTER TTHA;Lo;0;L;;;;;N;;;;; AAE6;MEETEI MAYEK LETTER DDA;Lo;0;L;;;;;N;;;;; AAE7;MEETEI MAYEK LETTER DDHA;Lo;0;L;;;;;N;;;;; AAE8;MEETEI MAYEK LETTER NNA;Lo;0;L;;;;;N;;;;; AAE9;MEETEI MAYEK LETTER SHA;Lo;0;L;;;;;N;;;;; AAEA;MEETEI MAYEK LETTER SSA;Lo;0;L;;;;;N;;;;; AAEB;MEETEI MAYEK VOWEL SIGN II;Mc;0;L;;;;;N;;;;; AAEC;MEETEI MAYEK VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; AAED;MEETEI MAYEK VOWEL SIGN AAI;Mn;0;NSM;;;;;N;;;;; AAEE;MEETEI MAYEK VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; AAEF;MEETEI MAYEK VOWEL SIGN AAU;Mc;0;L;;;;;N;;;;; AAF0;MEETEI MAYEK CHEIKHAN;Po;0;L;;;;;N;;;;; AAF1;MEETEI MAYEK AHANG KHUDAM;Po;0;L;;;;;N;;;;; AAF2;MEETEI MAYEK ANJI;Lo;0;L;;;;;N;;;;; AAF3;MEETEI MAYEK SYLLABLE REPETITION MARK;Lm;0;L;;;;;N;;;;; AAF4;MEETEI MAYEK WORD REPETITION MARK;Lm;0;L;;;;;N;;;;; AAF5;MEETEI MAYEK VOWEL SIGN VISARGA;Mc;0;L;;;;;N;;;;; AAF6;MEETEI MAYEK VIRAMA;Mn;9;NSM;;;;;N;;;;; AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;; AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;; AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;; AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;; AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;; AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;; AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;; AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;; AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;; AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;; AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;; AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;; AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;; AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;; AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;; AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;; AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;; AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;; AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;; AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;; AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;; AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;; AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;; AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;; AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;; AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;; AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;; AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;; AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;; AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;; AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;; AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;; AB30;LATIN SMALL LETTER BARRED ALPHA;Ll;0;L;;;;;N;;;;; AB31;LATIN SMALL LETTER A REVERSED-SCHWA;Ll;0;L;;;;;N;;;;; AB32;LATIN SMALL LETTER BLACKLETTER E;Ll;0;L;;;;;N;;;;; AB33;LATIN SMALL LETTER BARRED E;Ll;0;L;;;;;N;;;;; AB34;LATIN SMALL LETTER E WITH FLOURISH;Ll;0;L;;;;;N;;;;; AB35;LATIN SMALL LETTER LENIS F;Ll;0;L;;;;;N;;;;; AB36;LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB37;LATIN SMALL LETTER L WITH INVERTED LAZY S;Ll;0;L;;;;;N;;;;; AB38;LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Ll;0;L;;;;;N;;;;; AB39;LATIN SMALL LETTER L WITH MIDDLE RING;Ll;0;L;;;;;N;;;;; AB3A;LATIN SMALL LETTER M WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3B;LATIN SMALL LETTER N WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3C;LATIN SMALL LETTER ENG WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3D;LATIN SMALL LETTER BLACKLETTER O;Ll;0;L;;;;;N;;;;; AB3E;LATIN SMALL LETTER BLACKLETTER O WITH STROKE;Ll;0;L;;;;;N;;;;; AB3F;LATIN SMALL LETTER OPEN O WITH STROKE;Ll;0;L;;;;;N;;;;; AB40;LATIN SMALL LETTER INVERTED OE;Ll;0;L;;;;;N;;;;; AB41;LATIN SMALL LETTER TURNED OE WITH STROKE;Ll;0;L;;;;;N;;;;; AB42;LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE;Ll;0;L;;;;;N;;;;; AB43;LATIN SMALL LETTER TURNED O OPEN-O;Ll;0;L;;;;;N;;;;; AB44;LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE;Ll;0;L;;;;;N;;;;; AB45;LATIN SMALL LETTER STIRRUP R;Ll;0;L;;;;;N;;;;; AB46;LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG;Ll;0;L;;;;;N;;;;; AB47;LATIN SMALL LETTER R WITHOUT HANDLE;Ll;0;L;;;;;N;;;;; AB48;LATIN SMALL LETTER DOUBLE R;Ll;0;L;;;;;N;;;;; AB49;LATIN SMALL LETTER R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB4A;LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB4B;LATIN SMALL LETTER SCRIPT R;Ll;0;L;;;;;N;;;;; AB4C;LATIN SMALL LETTER SCRIPT R WITH RING;Ll;0;L;;;;;N;;;;; AB4D;LATIN SMALL LETTER BASELINE ESH;Ll;0;L;;;;;N;;;;; AB4E;LATIN SMALL LETTER U WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB4F;LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB50;LATIN SMALL LETTER UI;Ll;0;L;;;;;N;;;;; AB51;LATIN SMALL LETTER TURNED UI;Ll;0;L;;;;;N;;;;; AB52;LATIN SMALL LETTER U WITH LEFT HOOK;Ll;0;L;;;;;N;;;;; AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;;; AB54;LATIN SMALL LETTER CHI WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB55;LATIN SMALL LETTER CHI WITH LOW LEFT SERIF;Ll;0;L;;;;;N;;;;; AB56;LATIN SMALL LETTER X WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB57;LATIN SMALL LETTER X WITH LONG LEFT LEG;Ll;0;L;;;;;N;;;;; AB58;LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB59;LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF;Ll;0;L;;;;;N;;;;; AB5A;LATIN SMALL LETTER Y WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB5B;MODIFIER BREVE WITH INVERTED BREVE;Sk;0;L;;;;;N;;;;; AB5C;MODIFIER LETTER SMALL HENG;Lm;0;L; A727;;;;N;;;;; AB5D;MODIFIER LETTER SMALL L WITH INVERTED LAZY S;Lm;0;L; AB37;;;;N;;;;; AB5E;MODIFIER LETTER SMALL L WITH MIDDLE TILDE;Lm;0;L; 026B;;;;N;;;;; AB5F;MODIFIER LETTER SMALL U WITH LEFT HOOK;Lm;0;L; AB52;;;;N;;;;; AB64;LATIN SMALL LETTER INVERTED ALPHA;Ll;0;L;;;;;N;;;;; AB65;GREEK LETTER SMALL CAPITAL OMEGA;Ll;0;L;;;;;N;;;;; ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;; ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;; ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;; ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;; ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;; ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;; ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;; ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;; ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;; ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;; ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;; ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;; ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;; ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;; ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;; ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;; ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;; ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;; ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;; ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;; ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;; ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;; ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;; ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;; ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;; ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;; ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;; ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;; ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;; ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;; ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;; ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;; ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;; ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;; ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;; ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;; ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;; ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;; ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;; ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;; ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;; ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;; ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;; ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AC00;;Lo;0;L;;;;;N;;;;; D7A3;;Lo;0;L;;;;;N;;;;; D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;; D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;; D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;; D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;; D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;; D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;; D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;; D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;; D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;; D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;; D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;; D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;; D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;; D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;; D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;; D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;; D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;; D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;; D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;; D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;; D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;; D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;; D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;; D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;; D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;; D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;; D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;; D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;; D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;; D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;; D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;; D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;; D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;; D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;; D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;; D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;; D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;; D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;; D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;; D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;; D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;; D800;;Cs;0;L;;;;;N;;;;; DB7F;;Cs;0;L;;;;;N;;;;; DB80;;Cs;0;L;;;;;N;;;;; DBFF;;Cs;0;L;;;;;N;;;;; DC00;;Cs;0;L;;;;;N;;;;; DFFF;;Cs;0;L;;;;;N;;;;; E000;;Co;0;L;;;;;N;;;;; F8FF;;Co;0;L;;;;;N;;;;; F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;; F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;; F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;; F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;; F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;; F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;; F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;; F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;; FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;; FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; FA2E;CJK COMPATIBILITY IDEOGRAPH-FA2E;Lo;0;L;90DE;;;;N;;;;; FA2F;CJK COMPATIBILITY IDEOGRAPH-FA2F;Lo;0;L;96B7;;;;N;;;;; FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;; FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;; FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;; FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;; FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;; FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;; FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;; FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;; FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;; FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;; FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;; FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;; FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;; FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;; FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;; FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;; FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;; FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;; FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;; FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;; FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;; FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;; FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;; FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;; FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;; FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;; FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;; FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;; FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;; FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;; FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;; FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;; FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;; FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;; FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;; FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;; FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;; FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;; FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;; FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;; FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;; FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;; FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;; FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;; FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;; FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;; FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;; FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;; FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;; FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;; FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;; FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;; FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;; FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;; FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;; FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;; FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;; FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;; FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;; FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;; FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;; FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;; FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;; FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;; FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;; FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;; FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;; FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;; FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;; FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;; FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;; FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;; FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;; FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;; FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;; FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;; FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;; FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;; FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;; FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;; FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;; FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;; FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;; FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;; FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;; FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;; FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;; FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;; FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;; FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;; FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;; FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;; FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;; FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;; FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;; FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;; FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;; FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;; FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;; FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;; FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;; FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;; FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;; FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;; FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;; FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;; FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;; FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;; FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;; FB00;LATIN SMALL LIGATURE FF;Ll;0;L; 0066 0066;;;;N;;;;; FB01;LATIN SMALL LIGATURE FI;Ll;0;L; 0066 0069;;;;N;;;;; FB02;LATIN SMALL LIGATURE FL;Ll;0;L; 0066 006C;;;;N;;;;; FB03;LATIN SMALL LIGATURE FFI;Ll;0;L; 0066 0066 0069;;;;N;;;;; FB04;LATIN SMALL LIGATURE FFL;Ll;0;L; 0066 0066 006C;;;;N;;;;; FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L; 017F 0074;;;;N;;;;; FB06;LATIN SMALL LIGATURE ST;Ll;0;L; 0073 0074;;;;N;;;;; FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L; 0574 0576;;;;N;;;;; FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L; 0574 0565;;;;N;;;;; FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L; 0574 056B;;;;N;;;;; FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L; 057E 0576;;;;N;;;;; FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L; 0574 056D;;;;N;;;;; FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R; 05E2;;;;N;;;;; FB21;HEBREW LETTER WIDE ALEF;Lo;0;R; 05D0;;;;N;;;;; FB22;HEBREW LETTER WIDE DALET;Lo;0;R; 05D3;;;;N;;;;; FB23;HEBREW LETTER WIDE HE;Lo;0;R; 05D4;;;;N;;;;; FB24;HEBREW LETTER WIDE KAF;Lo;0;R; 05DB;;;;N;;;;; FB25;HEBREW LETTER WIDE LAMED;Lo;0;R; 05DC;;;;N;;;;; FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R; 05DD;;;;N;;;;; FB27;HEBREW LETTER WIDE RESH;Lo;0;R; 05E8;;;;N;;;;; FB28;HEBREW LETTER WIDE TAV;Lo;0;R; 05EA;;;;N;;;;; FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R; 05D0 05DC;;;;N;;;;; FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL; 0671;;;;N;;;;; FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL; 0671;;;;N;;;;; FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL; 067B;;;;N;;;;; FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL; 067B;;;;N;;;;; FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL; 067E;;;;N;;;;; FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL; 067E;;;;N;;;;; FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL; 0680;;;;N;;;;; FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL; 0680;;;;N;;;;; FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL; 067A;;;;N;;;;; FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL; 067A;;;;N;;;;; FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL; 067F;;;;N;;;;; FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL; 067F;;;;N;;;;; FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL; 0679;;;;N;;;;; FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL; 0679;;;;N;;;;; FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL; 06A6;;;;N;;;;; FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL; 0684;;;;N;;;;; FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL; 0684;;;;N;;;;; FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL; 0683;;;;N;;;;; FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL; 0683;;;;N;;;;; FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL; 0686;;;;N;;;;; FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL; 0686;;;;N;;;;; FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL; 0687;;;;N;;;;; FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL; 0687;;;;N;;;;; FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL; 068D;;;;N;;;;; FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL; 068D;;;;N;;;;; FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL; 068C;;;;N;;;;; FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL; 068C;;;;N;;;;; FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL; 068E;;;;N;;;;; FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL; 068E;;;;N;;;;; FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL; 0688;;;;N;;;;; FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL; 0688;;;;N;;;;; FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL; 0698;;;;N;;;;; FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL; 0698;;;;N;;;;; FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL; 0691;;;;N;;;;; FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL; 0691;;;;N;;;;; FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL; 06A9;;;;N;;;;; FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL; 06AF;;;;N;;;;; FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL; 06B3;;;;N;;;;; FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL; 06BA;;;;N;;;;; FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL; 06BA;;;;N;;;;; FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL; 06C0;;;;N;;;;; FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL; 06D2;;;;N;;;;; FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL; 06D2;;;;N;;;;; FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 06D3;;;;N;;;;; FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 06D3;;;;N;;;;; FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;; FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;; FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;; FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;; FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;; FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;; FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL; 06C7;;;;N;;;;; FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL; 06C6;;;;N;;;;; FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL; 06C8;;;;N;;;;; FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0677;;;;N;;;;; FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL; 06CB;;;;N;;;;; FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL; 06CB;;;;N;;;;; FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL; 06C5;;;;N;;;;; FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL; 06C9;;;;N;;;;; FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL; 0649;;;;N;;;;; FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL; 0626 0627;;;;N;;;;; FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL; 0626 0648;;;;N;;;;; FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062B 062C;;;;N;;;;; FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL; 062E 062D;;;;N;;;;; FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0645 0649;;;;N;;;;; FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL; 0645 064A;;;;N;;;;; FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0647 0649;;;;N;;;;; FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL; 0647 064A;;;;N;;;;; FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0630 0670;;;;N;;;;; FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0631 0670;;;;N;;;;; FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C 0651;;;;N;;;;; FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D 0651;;;;N;;;;; FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL; 0020 064E 0651;;;;N;;;;; FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F 0651;;;;N;;;;; FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL; 0020 0650 0651;;;;N;;;;; FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0020 0651 0670;;;;N;;;;; FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL; 0626 0631;;;;N;;;;; FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL; 0626 0632;;;;N;;;;; FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL; 0626 0646;;;;N;;;;; FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL; 0626 064A;;;;N;;;;; FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL; 0628 0631;;;;N;;;;; FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL; 0628 0632;;;;N;;;;; FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL; 0628 0646;;;;N;;;;; FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0628 0649;;;;N;;;;; FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL; 0628 064A;;;;N;;;;; FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL; 062A 0631;;;;N;;;;; FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL; 062A 0632;;;;N;;;;; FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL; 062A 0646;;;;N;;;;; FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0649;;;;N;;;;; FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL; 062A 064A;;;;N;;;;; FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL; 062B 0631;;;;N;;;;; FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL; 062B 0632;;;;N;;;;; FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL; 062B 0646;;;;N;;;;; FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062B 0649;;;;N;;;;; FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL; 062B 064A;;;;N;;;;; FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0641 0649;;;;N;;;;; FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL; 0641 064A;;;;N;;;;; FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0642 0649;;;;N;;;;; FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL; 0642 064A;;;;N;;;;; FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL; 0643 0627;;;;N;;;;; FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0643 0649;;;;N;;;;; FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL; 0643 064A;;;;N;;;;; FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 0649;;;;N;;;;; FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL; 0644 064A;;;;N;;;;; FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL; 0645 0627;;;;N;;;;; FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL; 0646 0631;;;;N;;;;; FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL; 0646 0632;;;;N;;;;; FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL; 0646 0646;;;;N;;;;; FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0649;;;;N;;;;; FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL; 0646 064A;;;;N;;;;; FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL; 0649 0670;;;;N;;;;; FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL; 064A 0631;;;;N;;;;; FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL; 064A 0632;;;;N;;;;; FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL; 064A 0646;;;;N;;;;; FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 064A 0649;;;;N;;;;; FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL; 064A 064A;;;;N;;;;; FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL; 0626 062C;;;;N;;;;; FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL; 0626 062D;;;;N;;;;; FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL; 0626 062E;;;;N;;;;; FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL; 0628 062C;;;;N;;;;; FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL; 0628 062D;;;;N;;;;; FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL; 0628 062E;;;;N;;;;; FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062C;;;;N;;;;; FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL; 062A 062D;;;;N;;;;; FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL; 062A 062E;;;;N;;;;; FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 062D;;;;N;;;;; FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062C 0645;;;;N;;;;; FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062D 062C;;;;N;;;;; FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062D 0645;;;;N;;;;; FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 062E 062C;;;;N;;;;; FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062E 0645;;;;N;;;;; FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D;;;;N;;;;; FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL; 0635 062E;;;;N;;;;; FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645;;;;N;;;;; FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL; 0636 062C;;;;N;;;;; FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL; 0636 062D;;;;N;;;;; FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL; 0636 062E;;;;N;;;;; FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL; 0636 0645;;;;N;;;;; FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL; 0637 062D;;;;N;;;;; FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL; 0639 062C;;;;N;;;;; FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645;;;;N;;;;; FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL; 063A 062C;;;;N;;;;; FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL; 063A 0645;;;;N;;;;; FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL; 0641 062C;;;;N;;;;; FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL; 0641 062D;;;;N;;;;; FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL; 0641 062E;;;;N;;;;; FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 0645;;;;N;;;;; FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL; 0642 062D;;;;N;;;;; FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL; 0642 0645;;;;N;;;;; FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL; 0643 062C;;;;N;;;;; FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL; 0643 062D;;;;N;;;;; FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL; 0643 062E;;;;N;;;;; FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C;;;;N;;;;; FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL; 0644 062D;;;;N;;;;; FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL; 0644 062E;;;;N;;;;; FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL; 0644 0647;;;;N;;;;; FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062C;;;;N;;;;; FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062D;;;;N;;;;; FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062E;;;;N;;;;; FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL; 0646 062C;;;;N;;;;; FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL; 0646 062D;;;;N;;;;; FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL; 0646 062E;;;;N;;;;; FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL; 0647 062C;;;;N;;;;; FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645;;;;N;;;;; FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL; 0647 0670;;;;N;;;;; FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL; 064A 062C;;;;N;;;;; FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL; 064A 062D;;;;N;;;;; FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL; 064A 062E;;;;N;;;;; FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL; 062B 0647;;;;N;;;;; FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL; 0640 064E 0651;;;;N;;;;; FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F 0651;;;;N;;;;; FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL; 0640 0650 0651;;;;N;;;;; FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0637 0649;;;;N;;;;; FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL; 0637 064A;;;;N;;;;; FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0649;;;;N;;;;; FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL; 0639 064A;;;;N;;;;; FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0649;;;;N;;;;; FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL; 063A 064A;;;;N;;;;; FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 0649;;;;N;;;;; FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL; 0633 064A;;;;N;;;;; FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0634 0649;;;;N;;;;; FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL; 0634 064A;;;;N;;;;; FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0649;;;;N;;;;; FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL; 062D 064A;;;;N;;;;; FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0649;;;;N;;;;; FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 064A;;;;N;;;;; FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062E 0649;;;;N;;;;; FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL; 062E 064A;;;;N;;;;; FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0635 0649;;;;N;;;;; FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL; 0635 064A;;;;N;;;;; FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 0649;;;;N;;;;; FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL; 0636 064A;;;;N;;;;; FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL; 0634 0631;;;;N;;;;; FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL; 0633 0631;;;;N;;;;; FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL; 0635 0631;;;;N;;;;; FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL; 0636 0631;;;;N;;;;; FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0627 064B;;;;N;;;;; FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;; FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;; FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062C 0645;;;;N;;;;; FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062D 0645;;;;N;;;;; FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062E 0645;;;;N;;;;; FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 062A 0645 062C;;;;N;;;;; FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062A 0645 062D;;;;N;;;;; FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 062A 0645 062E;;;;N;;;;; FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 0645 064A;;;;N;;;;; FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0645 0649;;;;N;;;;; FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062D 062C;;;;N;;;;; FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 062C 062D;;;;N;;;;; FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062C 0649;;;;N;;;;; FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0633 0645 062C;;;;N;;;;; FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0634 062C 064A;;;;N;;;;; FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 062D 0649;;;;N;;;;; FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645 0645;;;;N;;;;; FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0637 0645 064A;;;;N;;;;; FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0645 0649;;;;N;;;;; FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 063A 0645 0645;;;;N;;;;; FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 063A 0645 064A;;;;N;;;;; FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0645 0649;;;;N;;;;; FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0642 0645 0645;;;;N;;;;; FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0644 062D 064A;;;;N;;;;; FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 062D 0649;;;;N;;;;; FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062D 062C;;;;N;;;;; FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062D 0645;;;;N;;;;; FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062D 064A;;;;N;;;;; FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062C 062D;;;;N;;;;; FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062C 0645;;;;N;;;;; FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062E 062C;;;;N;;;;; FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062E 0645;;;;N;;;;; FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062C 062E;;;;N;;;;; FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0647 0645 062C;;;;N;;;;; FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645 0645;;;;N;;;;; FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062D 0645;;;;N;;;;; FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062D 0649;;;;N;;;;; FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062C 0649;;;;N;;;;; FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 0645 064A;;;;N;;;;; FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0645 0649;;;;N;;;;; FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062E 064A;;;;N;;;;; FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 062C 064A;;;;N;;;;; FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062C 0649;;;;N;;;;; FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 062A 062E 064A;;;;N;;;;; FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062E 0649;;;;N;;;;; FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 0645 064A;;;;N;;;;; FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0645 0649;;;;N;;;;; FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 0645 064A;;;;N;;;;; FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 062D 0649;;;;N;;;;; FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0645 0649;;;;N;;;;; FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062E 0649;;;;N;;;;; FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0635 062D 064A;;;;N;;;;; FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0634 062D 064A;;;;N;;;;; FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0636 062D 064A;;;;N;;;;; FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 062C 064A;;;;N;;;;; FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 0645 064A;;;;N;;;;; FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 064A 062D 064A;;;;N;;;;; FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 062C 064A;;;;N;;;;; FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 0645 064A;;;;N;;;;; FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 0645 064A;;;;N;;;;; FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0642 0645 064A;;;;N;;;;; FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0646 062D 064A;;;;N;;;;; FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0639 0645 064A;;;;N;;;;; FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0643 0645 064A;;;;N;;;;; FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062E 064A;;;;N;;;;; FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 062C 062D 064A;;;;N;;;;; FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 062C 064A;;;;N;;;;; FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 062C 064A;;;;N;;;;; FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0641 0645 064A;;;;N;;;;; FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062D 064A;;;;N;;;;; FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0633 062E 064A;;;;N;;;;; FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 062C 064A;;;;N;;;;; FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0635 0644 06D2;;;;N;;;;; FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0642 0644 06D2;;;;N;;;;; FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL; 0627 0644 0644 0647;;;;N;;;;; FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL; 0627 0643 0628 0631;;;;N;;;;; FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL; 0645 062D 0645 062F;;;;N;;;;; FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL; 0635 0644 0639 0645;;;;N;;;;; FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL; 0631 0633 0648 0644;;;;N;;;;; FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL; 0639 0644 064A 0647;;;;N;;;;; FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL; 0648 0633 0644 0645;;;;N;;;;; FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL; 0635 0644 0649;;;;N;;;;; FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL; 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL; 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; FDFC;RIAL SIGN;Sc;0;AL; 0631 06CC 0627 0644;;;;N;;;;; FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON; 002C;;;;N;;;;; FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;;;;; FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON; 003A;;;;N;;;;; FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON; 3016;;;;N;;;;; FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON; 3017;;;;N;;;;; FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON; 2026;;;;N;;;;; FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;; FE27;COMBINING LIGATURE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE28;COMBINING LIGATURE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE29;COMBINING TILDE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2A;COMBINING TILDE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2B;COMBINING MACRON LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2C;COMBINING MACRON RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2D;COMBINING CONJOINING MACRON BELOW;Mn;220;NSM;;;;;N;;;;; FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON; 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON; 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON; 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON; 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON; 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON; 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON; 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON; 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON; 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON; 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON; 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;N;;;;; FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;N;;;;; FE49;DASHED OVERLINE;Po;0;ON; 203E;;;;N;SPACING DASHED OVERSCORE;;;; FE4A;CENTRELINE OVERLINE;Po;0;ON; 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; FE4B;WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING WAVY OVERSCORE;;;; FE4C;DOUBLE WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; FE4D;DASHED LOW LINE;Pc;0;ON; 005F;;;;N;SPACING DASHED UNDERSCORE;;;; FE4E;CENTRELINE LOW LINE;Pc;0;ON; 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; FE4F;WAVY LOW LINE;Pc;0;ON; 005F;;;;N;SPACING WAVY UNDERSCORE;;;; FE50;SMALL COMMA;Po;0;CS; 002C;;;;N;;;;; FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FE52;SMALL FULL STOP;Po;0;CS; 002E;;;;N;SMALL PERIOD;;;; FE54;SMALL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FE55;SMALL COLON;Po;0;CS; 003A;;;;N;;;;; FE56;SMALL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FE57;SMALL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FE58;SMALL EM DASH;Pd;0;ON; 2014;;;;N;;;;; FE59;SMALL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SMALL OPENING PARENTHESIS;;;; FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;; FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;; FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;; FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;; FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;; FE5F;SMALL NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FE60;SMALL AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FE61;SMALL ASTERISK;Po;0;ON; 002A;;;;N;;;;; FE62;SMALL PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FE63;SMALL HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; FE64;SMALL LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; FE65;SMALL GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; FE66;SMALL EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FE68;SMALL REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;SMALL BACKSLASH;;;; FE69;SMALL DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FE6A;SMALL PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FE6B;SMALL COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL; 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL; 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL; 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL; 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL; 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL; 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL; 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL; 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL; 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL; 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL; 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; FF02;FULLWIDTH QUOTATION MARK;Po;0;ON; 0022;;;;N;;;;; FF03;FULLWIDTH NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; FF05;FULLWIDTH PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; FF06;FULLWIDTH AMPERSAND;Po;0;ON; 0026;;;;N;;;;; FF07;FULLWIDTH APOSTROPHE;Po;0;ON; 0027;;;;N;;;;; FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; FF0A;FULLWIDTH ASTERISK;Po;0;ON; 002A;;;;N;;;;; FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; FF0C;FULLWIDTH COMMA;Po;0;CS; 002C;;;;N;;;;; FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; FF0E;FULLWIDTH FULL STOP;Po;0;CS; 002E;;;;N;FULLWIDTH PERIOD;;;; FF0F;FULLWIDTH SOLIDUS;Po;0;CS; 002F;;;;N;FULLWIDTH SLASH;;;; FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; FF11;FULLWIDTH DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; FF12;FULLWIDTH DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; FF13;FULLWIDTH DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; FF16;FULLWIDTH DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; FF19;FULLWIDTH DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; FF1A;FULLWIDTH COLON;Po;0;CS; 003A;;;;N;;;;; FF1B;FULLWIDTH SEMICOLON;Po;0;ON; 003B;;;;N;;;;; FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; FF1F;FULLWIDTH QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L; 0041;;;;N;;;;FF41; FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L; 0042;;;;N;;;;FF42; FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L; 0043;;;;N;;;;FF43; FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L; 0044;;;;N;;;;FF44; FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L; 0045;;;;N;;;;FF45; FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L; 0046;;;;N;;;;FF46; FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L; 0047;;;;N;;;;FF47; FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L; 0048;;;;N;;;;FF48; FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L; 0049;;;;N;;;;FF49; FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L; 004A;;;;N;;;;FF4A; FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L; 004B;;;;N;;;;FF4B; FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L; 004C;;;;N;;;;FF4C; FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L; 004D;;;;N;;;;FF4D; FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L; 004E;;;;N;;;;FF4E; FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L; 004F;;;;N;;;;FF4F; FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L; 0050;;;;N;;;;FF50; FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L; 0051;;;;N;;;;FF51; FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L; 0052;;;;N;;;;FF52; FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L; 0053;;;;N;;;;FF53; FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L; 0054;;;;N;;;;FF54; FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L; 0055;;;;N;;;;FF55; FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L; 0056;;;;N;;;;FF56; FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L; 0057;;;;N;;;;FF57; FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L; 0058;;;;N;;;;FF58; FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L; 0059;;;;N;;;;FF59; FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L; 005A;;;;N;;;;FF5A; FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;FULLWIDTH BACKSLASH;;;; FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON; 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; FF3F;FULLWIDTH LOW LINE;Pc;0;ON; 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON; 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L; 0061;;;;N;;;FF21;;FF21 FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L; 0062;;;;N;;;FF22;;FF22 FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L; 0063;;;;N;;;FF23;;FF23 FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L; 0064;;;;N;;;FF24;;FF24 FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L; 0065;;;;N;;;FF25;;FF25 FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L; 0066;;;;N;;;FF26;;FF26 FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L; 0067;;;;N;;;FF27;;FF27 FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L; 0068;;;;N;;;FF28;;FF28 FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L; 0069;;;;N;;;FF29;;FF29 FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L; 006A;;;;N;;;FF2A;;FF2A FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L; 006B;;;;N;;;FF2B;;FF2B FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L; 006C;;;;N;;;FF2C;;FF2C FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L; 006D;;;;N;;;FF2D;;FF2D FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L; 006E;;;;N;;;FF2E;;FF2E FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L; 006F;;;;N;;;FF2F;;FF2F FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L; 0070;;;;N;;;FF30;;FF30 FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L; 0071;;;;N;;;FF31;;FF31 FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L; 0072;;;;N;;;FF32;;FF32 FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L; 0073;;;;N;;;FF33;;FF33 FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L; 0074;;;;N;;;FF34;;FF34 FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L; 0075;;;;N;;;FF35;;FF35 FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L; 0076;;;;N;;;FF36;;FF36 FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L; 0077;;;;N;;;FF37;;FF37 FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L; 0078;;;;N;;;FF38;;FF38 FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L; 0079;;;;N;;;FF39;;FF39 FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L; 007A;;;;N;;;FF3A;;FF3A FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON; 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; FF5E;FULLWIDTH TILDE;Sm;0;ON; 007E;;;;N;FULLWIDTH SPACING TILDE;;;; FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON; 2985;;;;Y;;;;; FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON; 2986;;;;Y;;;;; FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON; 30FB;;;;N;;;;; FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L; 30F2;;;;N;;;;; FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L; 30A1;;;;N;;;;; FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L; 30A3;;;;N;;;;; FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L; 30A5;;;;N;;;;; FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L; 30A7;;;;N;;;;; FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L; 30A9;;;;N;;;;; FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L; 30E3;;;;N;;;;; FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L; 30E5;;;;N;;;;; FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L; 30E7;;;;N;;;;; FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L; 30C3;;;;N;;;;; FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L; 30FC;;;;N;;;;; FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L; 30A2;;;;N;;;;; FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L; 30A4;;;;N;;;;; FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L; 30A6;;;;N;;;;; FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L; 30A8;;;;N;;;;; FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L; 30AA;;;;N;;;;; FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L; 30AB;;;;N;;;;; FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L; 30AD;;;;N;;;;; FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L; 30AF;;;;N;;;;; FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L; 30B1;;;;N;;;;; FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L; 30B3;;;;N;;;;; FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L; 30B5;;;;N;;;;; FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L; 30B7;;;;N;;;;; FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L; 30B9;;;;N;;;;; FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L; 30BB;;;;N;;;;; FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L; 30BD;;;;N;;;;; FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L; 30BF;;;;N;;;;; FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L; 30C1;;;;N;;;;; FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L; 30C4;;;;N;;;;; FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L; 30C6;;;;N;;;;; FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L; 30C8;;;;N;;;;; FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L; 30CA;;;;N;;;;; FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L; 30CB;;;;N;;;;; FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L; 30CC;;;;N;;;;; FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L; 30CD;;;;N;;;;; FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L; 30CE;;;;N;;;;; FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L; 30CF;;;;N;;;;; FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L; 30D2;;;;N;;;;; FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L; 30D5;;;;N;;;;; FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L; 30D8;;;;N;;;;; FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L; 30DB;;;;N;;;;; FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L; 30DE;;;;N;;;;; FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L; 30DF;;;;N;;;;; FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L; 30E0;;;;N;;;;; FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L; 30E1;;;;N;;;;; FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L; 30E2;;;;N;;;;; FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L; 30E4;;;;N;;;;; FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L; 30E6;;;;N;;;;; FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L; 30E8;;;;N;;;;; FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L; 30E9;;;;N;;;;; FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L; 30EA;;;;N;;;;; FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L; 30EB;;;;N;;;;; FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L; 30EC;;;;N;;;;; FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L; 30ED;;;;N;;;;; FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L; 30EF;;;;N;;;;; FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L; 30F3;;;;N;;;;; FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L; 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L; 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L; 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L; 3134;;;;N;;;;; FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L; 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L; 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L; 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L; 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L; 3141;;;;N;;;;; FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L; 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L; 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L; 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L; 3145;;;;N;;;;; FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L; 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L; 3147;;;;N;;;;; FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L; 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L; 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L; 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L; 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L; 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L; 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L; 314E;;;;N;;;;; FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L; 314F;;;;N;;;;; FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L; 3150;;;;N;;;;; FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L; 3151;;;;N;;;;; FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L; 3152;;;;N;;;;; FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L; 3153;;;;N;;;;; FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L; 3154;;;;N;;;;; FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L; 3155;;;;N;;;;; FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L; 3156;;;;N;;;;; FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L; 3157;;;;N;;;;; FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L; 3158;;;;N;;;;; FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L; 3159;;;;N;;;;; FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L; 315A;;;;N;;;;; FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L; 315B;;;;N;;;;; FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L; 315C;;;;N;;;;; FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L; 315D;;;;N;;;;; FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L; 315E;;;;N;;;;; FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L; 315F;;;;N;;;;; FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L; 3160;;;;N;;;;; FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L; 3161;;;;N;;;;; FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L; 3162;;;;N;;;;; FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; FFE0;FULLWIDTH CENT SIGN;Sc;0;ET; 00A2;;;;N;;;;; FFE1;FULLWIDTH POUND SIGN;Sc;0;ET; 00A3;;;;N;;;;; FFE2;FULLWIDTH NOT SIGN;Sm;0;ON; 00AC;;;;N;;;;; FFE3;FULLWIDTH MACRON;Sk;0;ON; 00AF;;;;N;FULLWIDTH SPACING MACRON;;;; FFE4;FULLWIDTH BROKEN BAR;So;0;ON; 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; FFE5;FULLWIDTH YEN SIGN;Sc;0;ET; 00A5;;;;N;;;;; FFE6;FULLWIDTH WON SIGN;Sc;0;ET; 20A9;;;;N;;;;; FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON; 2502;;;;N;;;;; FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON; 2190;;;;N;;;;; FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON; 2191;;;;N;;;;; FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON; 2192;;;;N;;;;; FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON; 2193;;;;N;;;;; FFED;HALFWIDTH BLACK SQUARE;So;0;ON; 25A0;;;;N;;;;; FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON; 25CB;;;;N;;;;; FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;; FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;; FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;; FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;; 10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;; 10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;; 10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;; 10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;; 10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;; 10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;; 10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;; 10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;; 10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;; 1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;; 1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;; 1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;; 1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;; 1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;; 10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;; 10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;; 10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;; 10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;; 10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;; 10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;; 10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;; 10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;; 10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;; 10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;; 1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;; 1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;; 1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;; 1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;; 1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;; 1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;; 10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;; 10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;; 10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;; 10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;; 10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;; 10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;; 10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;; 10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;; 10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;; 1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;; 1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;; 1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;; 1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;; 1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;; 1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;; 10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;; 10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;; 10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;; 10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;; 10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;; 10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;; 10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;; 10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;; 10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;; 10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;; 1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;; 1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;; 1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;; 1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;; 10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;; 10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;; 10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;; 10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;; 10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;; 10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;; 10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;; 10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;; 10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;; 10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;; 1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;; 1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;; 1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;; 1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;; 10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;; 10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;; 10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;; 10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;; 10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;; 10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;; 10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;; 10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;; 10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;; 10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;; 1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;; 1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;; 1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;; 1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;; 10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;; 10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;; 10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;; 10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;; 10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;; 10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;; 10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;; 10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;; 10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;; 10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;; 1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;; 1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;; 1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;; 1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;; 1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;; 1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;; 10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;; 10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;; 10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;; 10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;; 10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;; 10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;; 10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;; 10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;; 10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;; 10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;; 1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;; 1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;; 1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;; 1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;; 1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;; 1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;; 100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;; 100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;; 100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;; 100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;; 100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;; 100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;; 100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;; 100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;; 100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;; 100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;; 100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;; 100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;; 100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;; 100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;; 100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;; 100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;; 100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;; 100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;; 100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;; 100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;; 100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;; 100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;; 100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;; 100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;; 100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;; 100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;; 100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;; 100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;; 100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;; 100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;; 100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;; 100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;; 100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;; 100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;; 100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;; 100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;; 100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;; 100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;; 100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;; 100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;; 100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;; 100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;; 100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;; 100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;; 100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;; 100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;; 100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;; 100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;; 100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;; 100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;; 100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;; 100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;; 100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;; 100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;; 100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;; 100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;; 100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;; 100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;; 100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;; 100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;; 100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;; 100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;; 100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;; 100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;; 100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;; 100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;; 100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;; 100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;; 100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;; 100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;; 100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;; 100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;; 100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;; 100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;; 100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;; 100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;; 100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;; 100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;; 100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;; 100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;; 100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;; 100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;; 100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;; 100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;; 100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;; 100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;; 100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;; 100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;; 100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;; 100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;; 100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;; 10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;; 10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;; 10102;AEGEAN CHECK MARK;Po;0;L;;;;;N;;;;; 10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;; 10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;; 10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;; 1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;; 1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;; 1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;; 1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;; 1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;; 1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;; 10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;; 10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;; 10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;; 10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;; 10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;; 10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;; 10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;; 10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;; 1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;; 1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;; 1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;; 1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;; 1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;; 10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;; 10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;; 10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;; 10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;; 10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;; 10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;; 10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;; 10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;; 10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;; 1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;; 1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;; 1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;; 1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;; 1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;; 10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;; 10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;; 10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;; 10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;; 10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;; 10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;; 10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;; 1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;; 1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;; 10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;; 10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;; 10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;; 10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;; 10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;; 10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;; 10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;; 10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;; 1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;; 1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;; 1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;; 1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;; 1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;; 1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;; 10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;; 10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;; 10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;; 10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;; 10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;; 10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;; 10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;; 10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;; 10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;; 10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;; 1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;; 1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;; 10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;; 10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;; 10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;; 10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;; 10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;; 10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;; 1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;; 1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;; 10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;; 10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;; 10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;; 10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;; 10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;; 10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;; 10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;; 1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;; 1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;; 1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;; 1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;; 10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;; 10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;; 10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;; 10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;; 10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;; 10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;; 10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;; 10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;; 10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;; 10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;; 1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; 1018B;GREEK ONE QUARTER SIGN;No;0;ON;;;;1/4;N;;;;; 1018C;GREEK SINUSOID SIGN;So;0;ON;;;;;N;;;;; 10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; 10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; 10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; 10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;; 10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;; 10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;; 10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;; 10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;; 1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;; 1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;; 101A0;GREEK SYMBOL TAU RHO;So;0;ON;;;;;N;;;;; 101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;; 101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;; 101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;; 101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;; 101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;; 101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;; 101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;; 101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;; 101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;; 101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;; 101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;; 101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;; 101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;; 101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;; 101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;; 101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;; 101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;; 101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;; 101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;; 101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;; 101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;; 101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;; 101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;; 101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;; 101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;; 101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;; 101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;; 101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;; 101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;; 101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;; 101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;; 101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;; 101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;; 101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;; 101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;; 101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;; 101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;; 101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;; 101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;; 101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;; 101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;; 101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;; 101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;; 101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;; 101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;; 101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;; 10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;; 10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;; 10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;; 10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;; 10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;; 10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;; 10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;; 10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;; 10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;; 10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;; 1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;; 1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;; 1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;; 1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;; 1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;; 1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;; 10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;; 10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;; 10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;; 10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;; 10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;; 10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;; 10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;; 10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;; 10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;; 10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;; 1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;; 1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;; 1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;; 102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;; 102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;; 102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;; 102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;; 102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;; 102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;; 102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;; 102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;; 102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;; 102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;; 102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;; 102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;; 102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;; 102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;; 102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;; 102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;; 102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;; 102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;; 102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;; 102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;; 102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;; 102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;; 102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;; 102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;; 102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;; 102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;; 102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;; 102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;; 102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;; 102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;; 102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;; 102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;; 102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;; 102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;; 102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;; 102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;; 102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;; 102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;; 102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;; 102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;; 102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;; 102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;; 102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;; 102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;; 102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;; 102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;; 102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;; 102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;; 102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;; 102E0;COPTIC EPACT THOUSANDS MARK;Mn;220;NSM;;;;;N;;;;; 102E1;COPTIC EPACT DIGIT ONE;No;0;EN;;;;1;N;;;;; 102E2;COPTIC EPACT DIGIT TWO;No;0;EN;;;;2;N;;;;; 102E3;COPTIC EPACT DIGIT THREE;No;0;EN;;;;3;N;;;;; 102E4;COPTIC EPACT DIGIT FOUR;No;0;EN;;;;4;N;;;;; 102E5;COPTIC EPACT DIGIT FIVE;No;0;EN;;;;5;N;;;;; 102E6;COPTIC EPACT DIGIT SIX;No;0;EN;;;;6;N;;;;; 102E7;COPTIC EPACT DIGIT SEVEN;No;0;EN;;;;7;N;;;;; 102E8;COPTIC EPACT DIGIT EIGHT;No;0;EN;;;;8;N;;;;; 102E9;COPTIC EPACT DIGIT NINE;No;0;EN;;;;9;N;;;;; 102EA;COPTIC EPACT NUMBER TEN;No;0;EN;;;;10;N;;;;; 102EB;COPTIC EPACT NUMBER TWENTY;No;0;EN;;;;20;N;;;;; 102EC;COPTIC EPACT NUMBER THIRTY;No;0;EN;;;;30;N;;;;; 102ED;COPTIC EPACT NUMBER FORTY;No;0;EN;;;;40;N;;;;; 102EE;COPTIC EPACT NUMBER FIFTY;No;0;EN;;;;50;N;;;;; 102EF;COPTIC EPACT NUMBER SIXTY;No;0;EN;;;;60;N;;;;; 102F0;COPTIC EPACT NUMBER SEVENTY;No;0;EN;;;;70;N;;;;; 102F1;COPTIC EPACT NUMBER EIGHTY;No;0;EN;;;;80;N;;;;; 102F2;COPTIC EPACT NUMBER NINETY;No;0;EN;;;;90;N;;;;; 102F3;COPTIC EPACT NUMBER ONE HUNDRED;No;0;EN;;;;100;N;;;;; 102F4;COPTIC EPACT NUMBER TWO HUNDRED;No;0;EN;;;;200;N;;;;; 102F5;COPTIC EPACT NUMBER THREE HUNDRED;No;0;EN;;;;300;N;;;;; 102F6;COPTIC EPACT NUMBER FOUR HUNDRED;No;0;EN;;;;400;N;;;;; 102F7;COPTIC EPACT NUMBER FIVE HUNDRED;No;0;EN;;;;500;N;;;;; 102F8;COPTIC EPACT NUMBER SIX HUNDRED;No;0;EN;;;;600;N;;;;; 102F9;COPTIC EPACT NUMBER SEVEN HUNDRED;No;0;EN;;;;700;N;;;;; 102FA;COPTIC EPACT NUMBER EIGHT HUNDRED;No;0;EN;;;;800;N;;;;; 102FB;COPTIC EPACT NUMBER NINE HUNDRED;No;0;EN;;;;900;N;;;;; 10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; 10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; 10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; 10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; 10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; 10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; 10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; 10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; 10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; 10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; 1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; 1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; 1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; 1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; 1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; 1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;; 10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; 10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; 10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; 10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; 10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; 10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; 10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; 10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;; 10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; 10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; 1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; 1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;; 1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;; 1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;; 1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;; 1031F;OLD ITALIC LETTER ESS;Lo;0;L;;;;;N;;;;; 10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; 10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; 10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; 10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; 10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; 10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; 10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; 10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; 1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; 1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; 1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; 1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; 1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; 1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; 10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; 10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;; 10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; 10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; 10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; 10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; 10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; 10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; 10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; 10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; 1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;; 10350;OLD PERMIC LETTER AN;Lo;0;L;;;;;N;;;;; 10351;OLD PERMIC LETTER BUR;Lo;0;L;;;;;N;;;;; 10352;OLD PERMIC LETTER GAI;Lo;0;L;;;;;N;;;;; 10353;OLD PERMIC LETTER DOI;Lo;0;L;;;;;N;;;;; 10354;OLD PERMIC LETTER E;Lo;0;L;;;;;N;;;;; 10355;OLD PERMIC LETTER ZHOI;Lo;0;L;;;;;N;;;;; 10356;OLD PERMIC LETTER DZHOI;Lo;0;L;;;;;N;;;;; 10357;OLD PERMIC LETTER ZATA;Lo;0;L;;;;;N;;;;; 10358;OLD PERMIC LETTER DZITA;Lo;0;L;;;;;N;;;;; 10359;OLD PERMIC LETTER I;Lo;0;L;;;;;N;;;;; 1035A;OLD PERMIC LETTER KOKE;Lo;0;L;;;;;N;;;;; 1035B;OLD PERMIC LETTER LEI;Lo;0;L;;;;;N;;;;; 1035C;OLD PERMIC LETTER MENOE;Lo;0;L;;;;;N;;;;; 1035D;OLD PERMIC LETTER NENOE;Lo;0;L;;;;;N;;;;; 1035E;OLD PERMIC LETTER VOOI;Lo;0;L;;;;;N;;;;; 1035F;OLD PERMIC LETTER PEEI;Lo;0;L;;;;;N;;;;; 10360;OLD PERMIC LETTER REI;Lo;0;L;;;;;N;;;;; 10361;OLD PERMIC LETTER SII;Lo;0;L;;;;;N;;;;; 10362;OLD PERMIC LETTER TAI;Lo;0;L;;;;;N;;;;; 10363;OLD PERMIC LETTER U;Lo;0;L;;;;;N;;;;; 10364;OLD PERMIC LETTER CHERY;Lo;0;L;;;;;N;;;;; 10365;OLD PERMIC LETTER SHOOI;Lo;0;L;;;;;N;;;;; 10366;OLD PERMIC LETTER SHCHOOI;Lo;0;L;;;;;N;;;;; 10367;OLD PERMIC LETTER YRY;Lo;0;L;;;;;N;;;;; 10368;OLD PERMIC LETTER YERU;Lo;0;L;;;;;N;;;;; 10369;OLD PERMIC LETTER O;Lo;0;L;;;;;N;;;;; 1036A;OLD PERMIC LETTER OO;Lo;0;L;;;;;N;;;;; 1036B;OLD PERMIC LETTER EF;Lo;0;L;;;;;N;;;;; 1036C;OLD PERMIC LETTER HA;Lo;0;L;;;;;N;;;;; 1036D;OLD PERMIC LETTER TSIU;Lo;0;L;;;;;N;;;;; 1036E;OLD PERMIC LETTER VER;Lo;0;L;;;;;N;;;;; 1036F;OLD PERMIC LETTER YER;Lo;0;L;;;;;N;;;;; 10370;OLD PERMIC LETTER YERI;Lo;0;L;;;;;N;;;;; 10371;OLD PERMIC LETTER YAT;Lo;0;L;;;;;N;;;;; 10372;OLD PERMIC LETTER IE;Lo;0;L;;;;;N;;;;; 10373;OLD PERMIC LETTER YU;Lo;0;L;;;;;N;;;;; 10374;OLD PERMIC LETTER YA;Lo;0;L;;;;;N;;;;; 10375;OLD PERMIC LETTER IA;Lo;0;L;;;;;N;;;;; 10376;COMBINING OLD PERMIC LETTER AN;Mn;230;NSM;;;;;N;;;;; 10377;COMBINING OLD PERMIC LETTER DOI;Mn;230;NSM;;;;;N;;;;; 10378;COMBINING OLD PERMIC LETTER ZATA;Mn;230;NSM;;;;;N;;;;; 10379;COMBINING OLD PERMIC LETTER NENOE;Mn;230;NSM;;;;;N;;;;; 1037A;COMBINING OLD PERMIC LETTER SII;Mn;230;NSM;;;;;N;;;;; 10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;; 10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;; 10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;; 10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;; 10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;; 10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;; 10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;; 10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;; 10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;; 10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;; 1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;; 1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;; 1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;; 1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;; 1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;; 1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;; 10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;; 10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;; 10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;; 10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;; 10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;; 10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;; 10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;; 10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;; 10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;; 10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;; 1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;; 1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;; 1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;; 1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;; 1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;; 103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;; 103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;; 103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;; 103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;; 103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;; 103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;; 103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;; 103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;; 103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;; 103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;; 103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;; 103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;; 103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;; 103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;; 103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;; 103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;; 103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;; 103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;; 103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;; 103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;; 103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;; 103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;; 103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;; 103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;; 103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;; 103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;; 103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;; 103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;; 103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;; 103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;; 103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;; 103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;; 103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;; 103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;; 103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;; 103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;; 103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;; 103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;; 103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;; 103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;; 103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;; 103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;; 103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;; 103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;; 103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;; 103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;; 103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;; 103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;; 103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;; 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; 10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; 10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; 10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; 10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; 10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; 10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; 10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; 10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; 10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; 1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; 1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; 1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; 1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; 1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; 1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; 10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; 10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; 10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; 10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; 10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; 10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; 10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; 10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; 10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; 10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; 1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; 1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; 1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; 1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; 1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; 1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; 10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; 10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; 10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; 10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; 10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; 10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; 10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E; 10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A 10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B 10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C 10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D 10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E 10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F 10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A 10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B 10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C 10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D 10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E 10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F 10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426 1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; 10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;; 10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;; 10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;; 10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;; 10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;; 10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;; 10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;; 10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;; 10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;; 1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;; 1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;; 1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;; 1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;; 1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;; 1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;; 10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;; 10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;; 10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;; 10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;; 10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;; 10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;; 10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;; 10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;; 10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;; 10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;; 1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;; 1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;; 1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;; 1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;; 1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;; 1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;; 10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;; 10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;; 10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;; 10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;; 10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;; 10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;; 10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;; 10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;; 10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;; 10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;; 1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;; 1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;; 1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;; 1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;; 1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;; 1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;; 10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;; 10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;; 10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;; 10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;; 10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;; 10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;; 10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;; 10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;; 10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;; 10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;; 1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;; 1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;; 1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;; 1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;; 1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;; 1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;; 10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;; 10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;; 10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;; 10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;; 10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;; 10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;; 10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;; 10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;; 10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;; 10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;; 1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;; 1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;; 1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;; 1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;; 104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 10500;ELBASAN LETTER A;Lo;0;L;;;;;N;;;;; 10501;ELBASAN LETTER BE;Lo;0;L;;;;;N;;;;; 10502;ELBASAN LETTER CE;Lo;0;L;;;;;N;;;;; 10503;ELBASAN LETTER CHE;Lo;0;L;;;;;N;;;;; 10504;ELBASAN LETTER DE;Lo;0;L;;;;;N;;;;; 10505;ELBASAN LETTER NDE;Lo;0;L;;;;;N;;;;; 10506;ELBASAN LETTER DHE;Lo;0;L;;;;;N;;;;; 10507;ELBASAN LETTER EI;Lo;0;L;;;;;N;;;;; 10508;ELBASAN LETTER E;Lo;0;L;;;;;N;;;;; 10509;ELBASAN LETTER FE;Lo;0;L;;;;;N;;;;; 1050A;ELBASAN LETTER GE;Lo;0;L;;;;;N;;;;; 1050B;ELBASAN LETTER GJE;Lo;0;L;;;;;N;;;;; 1050C;ELBASAN LETTER HE;Lo;0;L;;;;;N;;;;; 1050D;ELBASAN LETTER I;Lo;0;L;;;;;N;;;;; 1050E;ELBASAN LETTER JE;Lo;0;L;;;;;N;;;;; 1050F;ELBASAN LETTER KE;Lo;0;L;;;;;N;;;;; 10510;ELBASAN LETTER LE;Lo;0;L;;;;;N;;;;; 10511;ELBASAN LETTER LLE;Lo;0;L;;;;;N;;;;; 10512;ELBASAN LETTER ME;Lo;0;L;;;;;N;;;;; 10513;ELBASAN LETTER NE;Lo;0;L;;;;;N;;;;; 10514;ELBASAN LETTER NA;Lo;0;L;;;;;N;;;;; 10515;ELBASAN LETTER NJE;Lo;0;L;;;;;N;;;;; 10516;ELBASAN LETTER O;Lo;0;L;;;;;N;;;;; 10517;ELBASAN LETTER PE;Lo;0;L;;;;;N;;;;; 10518;ELBASAN LETTER QE;Lo;0;L;;;;;N;;;;; 10519;ELBASAN LETTER RE;Lo;0;L;;;;;N;;;;; 1051A;ELBASAN LETTER RRE;Lo;0;L;;;;;N;;;;; 1051B;ELBASAN LETTER SE;Lo;0;L;;;;;N;;;;; 1051C;ELBASAN LETTER SHE;Lo;0;L;;;;;N;;;;; 1051D;ELBASAN LETTER TE;Lo;0;L;;;;;N;;;;; 1051E;ELBASAN LETTER THE;Lo;0;L;;;;;N;;;;; 1051F;ELBASAN LETTER U;Lo;0;L;;;;;N;;;;; 10520;ELBASAN LETTER VE;Lo;0;L;;;;;N;;;;; 10521;ELBASAN LETTER XE;Lo;0;L;;;;;N;;;;; 10522;ELBASAN LETTER Y;Lo;0;L;;;;;N;;;;; 10523;ELBASAN LETTER ZE;Lo;0;L;;;;;N;;;;; 10524;ELBASAN LETTER ZHE;Lo;0;L;;;;;N;;;;; 10525;ELBASAN LETTER GHE;Lo;0;L;;;;;N;;;;; 10526;ELBASAN LETTER GHAMMA;Lo;0;L;;;;;N;;;;; 10527;ELBASAN LETTER KHE;Lo;0;L;;;;;N;;;;; 10530;CAUCASIAN ALBANIAN LETTER ALT;Lo;0;L;;;;;N;;;;; 10531;CAUCASIAN ALBANIAN LETTER BET;Lo;0;L;;;;;N;;;;; 10532;CAUCASIAN ALBANIAN LETTER GIM;Lo;0;L;;;;;N;;;;; 10533;CAUCASIAN ALBANIAN LETTER DAT;Lo;0;L;;;;;N;;;;; 10534;CAUCASIAN ALBANIAN LETTER EB;Lo;0;L;;;;;N;;;;; 10535;CAUCASIAN ALBANIAN LETTER ZARL;Lo;0;L;;;;;N;;;;; 10536;CAUCASIAN ALBANIAN LETTER EYN;Lo;0;L;;;;;N;;;;; 10537;CAUCASIAN ALBANIAN LETTER ZHIL;Lo;0;L;;;;;N;;;;; 10538;CAUCASIAN ALBANIAN LETTER TAS;Lo;0;L;;;;;N;;;;; 10539;CAUCASIAN ALBANIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1053A;CAUCASIAN ALBANIAN LETTER YOWD;Lo;0;L;;;;;N;;;;; 1053B;CAUCASIAN ALBANIAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 1053C;CAUCASIAN ALBANIAN LETTER IRB;Lo;0;L;;;;;N;;;;; 1053D;CAUCASIAN ALBANIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1053E;CAUCASIAN ALBANIAN LETTER LAN;Lo;0;L;;;;;N;;;;; 1053F;CAUCASIAN ALBANIAN LETTER INYA;Lo;0;L;;;;;N;;;;; 10540;CAUCASIAN ALBANIAN LETTER XEYN;Lo;0;L;;;;;N;;;;; 10541;CAUCASIAN ALBANIAN LETTER DYAN;Lo;0;L;;;;;N;;;;; 10542;CAUCASIAN ALBANIAN LETTER CAR;Lo;0;L;;;;;N;;;;; 10543;CAUCASIAN ALBANIAN LETTER JHOX;Lo;0;L;;;;;N;;;;; 10544;CAUCASIAN ALBANIAN LETTER KAR;Lo;0;L;;;;;N;;;;; 10545;CAUCASIAN ALBANIAN LETTER LYIT;Lo;0;L;;;;;N;;;;; 10546;CAUCASIAN ALBANIAN LETTER HEYT;Lo;0;L;;;;;N;;;;; 10547;CAUCASIAN ALBANIAN LETTER QAY;Lo;0;L;;;;;N;;;;; 10548;CAUCASIAN ALBANIAN LETTER AOR;Lo;0;L;;;;;N;;;;; 10549;CAUCASIAN ALBANIAN LETTER CHOY;Lo;0;L;;;;;N;;;;; 1054A;CAUCASIAN ALBANIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1054B;CAUCASIAN ALBANIAN LETTER CYAY;Lo;0;L;;;;;N;;;;; 1054C;CAUCASIAN ALBANIAN LETTER MAQ;Lo;0;L;;;;;N;;;;; 1054D;CAUCASIAN ALBANIAN LETTER QAR;Lo;0;L;;;;;N;;;;; 1054E;CAUCASIAN ALBANIAN LETTER NOWC;Lo;0;L;;;;;N;;;;; 1054F;CAUCASIAN ALBANIAN LETTER DZYAY;Lo;0;L;;;;;N;;;;; 10550;CAUCASIAN ALBANIAN LETTER SHAK;Lo;0;L;;;;;N;;;;; 10551;CAUCASIAN ALBANIAN LETTER JAYN;Lo;0;L;;;;;N;;;;; 10552;CAUCASIAN ALBANIAN LETTER ON;Lo;0;L;;;;;N;;;;; 10553;CAUCASIAN ALBANIAN LETTER TYAY;Lo;0;L;;;;;N;;;;; 10554;CAUCASIAN ALBANIAN LETTER FAM;Lo;0;L;;;;;N;;;;; 10555;CAUCASIAN ALBANIAN LETTER DZAY;Lo;0;L;;;;;N;;;;; 10556;CAUCASIAN ALBANIAN LETTER CHAT;Lo;0;L;;;;;N;;;;; 10557;CAUCASIAN ALBANIAN LETTER PEN;Lo;0;L;;;;;N;;;;; 10558;CAUCASIAN ALBANIAN LETTER GHEYS;Lo;0;L;;;;;N;;;;; 10559;CAUCASIAN ALBANIAN LETTER RAT;Lo;0;L;;;;;N;;;;; 1055A;CAUCASIAN ALBANIAN LETTER SEYK;Lo;0;L;;;;;N;;;;; 1055B;CAUCASIAN ALBANIAN LETTER VEYZ;Lo;0;L;;;;;N;;;;; 1055C;CAUCASIAN ALBANIAN LETTER TIWR;Lo;0;L;;;;;N;;;;; 1055D;CAUCASIAN ALBANIAN LETTER SHOY;Lo;0;L;;;;;N;;;;; 1055E;CAUCASIAN ALBANIAN LETTER IWN;Lo;0;L;;;;;N;;;;; 1055F;CAUCASIAN ALBANIAN LETTER CYAW;Lo;0;L;;;;;N;;;;; 10560;CAUCASIAN ALBANIAN LETTER CAYN;Lo;0;L;;;;;N;;;;; 10561;CAUCASIAN ALBANIAN LETTER YAYD;Lo;0;L;;;;;N;;;;; 10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;; 10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;; 1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;; 10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;; 10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;; 10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;; 10603;LINEAR A SIGN AB004;Lo;0;L;;;;;N;;;;; 10604;LINEAR A SIGN AB005;Lo;0;L;;;;;N;;;;; 10605;LINEAR A SIGN AB006;Lo;0;L;;;;;N;;;;; 10606;LINEAR A SIGN AB007;Lo;0;L;;;;;N;;;;; 10607;LINEAR A SIGN AB008;Lo;0;L;;;;;N;;;;; 10608;LINEAR A SIGN AB009;Lo;0;L;;;;;N;;;;; 10609;LINEAR A SIGN AB010;Lo;0;L;;;;;N;;;;; 1060A;LINEAR A SIGN AB011;Lo;0;L;;;;;N;;;;; 1060B;LINEAR A SIGN AB013;Lo;0;L;;;;;N;;;;; 1060C;LINEAR A SIGN AB016;Lo;0;L;;;;;N;;;;; 1060D;LINEAR A SIGN AB017;Lo;0;L;;;;;N;;;;; 1060E;LINEAR A SIGN AB020;Lo;0;L;;;;;N;;;;; 1060F;LINEAR A SIGN AB021;Lo;0;L;;;;;N;;;;; 10610;LINEAR A SIGN AB021F;Lo;0;L;;;;;N;;;;; 10611;LINEAR A SIGN AB021M;Lo;0;L;;;;;N;;;;; 10612;LINEAR A SIGN AB022;Lo;0;L;;;;;N;;;;; 10613;LINEAR A SIGN AB022F;Lo;0;L;;;;;N;;;;; 10614;LINEAR A SIGN AB022M;Lo;0;L;;;;;N;;;;; 10615;LINEAR A SIGN AB023;Lo;0;L;;;;;N;;;;; 10616;LINEAR A SIGN AB023M;Lo;0;L;;;;;N;;;;; 10617;LINEAR A SIGN AB024;Lo;0;L;;;;;N;;;;; 10618;LINEAR A SIGN AB026;Lo;0;L;;;;;N;;;;; 10619;LINEAR A SIGN AB027;Lo;0;L;;;;;N;;;;; 1061A;LINEAR A SIGN AB028;Lo;0;L;;;;;N;;;;; 1061B;LINEAR A SIGN A028B;Lo;0;L;;;;;N;;;;; 1061C;LINEAR A SIGN AB029;Lo;0;L;;;;;N;;;;; 1061D;LINEAR A SIGN AB030;Lo;0;L;;;;;N;;;;; 1061E;LINEAR A SIGN AB031;Lo;0;L;;;;;N;;;;; 1061F;LINEAR A SIGN AB034;Lo;0;L;;;;;N;;;;; 10620;LINEAR A SIGN AB037;Lo;0;L;;;;;N;;;;; 10621;LINEAR A SIGN AB038;Lo;0;L;;;;;N;;;;; 10622;LINEAR A SIGN AB039;Lo;0;L;;;;;N;;;;; 10623;LINEAR A SIGN AB040;Lo;0;L;;;;;N;;;;; 10624;LINEAR A SIGN AB041;Lo;0;L;;;;;N;;;;; 10625;LINEAR A SIGN AB044;Lo;0;L;;;;;N;;;;; 10626;LINEAR A SIGN AB045;Lo;0;L;;;;;N;;;;; 10627;LINEAR A SIGN AB046;Lo;0;L;;;;;N;;;;; 10628;LINEAR A SIGN AB047;Lo;0;L;;;;;N;;;;; 10629;LINEAR A SIGN AB048;Lo;0;L;;;;;N;;;;; 1062A;LINEAR A SIGN AB049;Lo;0;L;;;;;N;;;;; 1062B;LINEAR A SIGN AB050;Lo;0;L;;;;;N;;;;; 1062C;LINEAR A SIGN AB051;Lo;0;L;;;;;N;;;;; 1062D;LINEAR A SIGN AB053;Lo;0;L;;;;;N;;;;; 1062E;LINEAR A SIGN AB054;Lo;0;L;;;;;N;;;;; 1062F;LINEAR A SIGN AB055;Lo;0;L;;;;;N;;;;; 10630;LINEAR A SIGN AB056;Lo;0;L;;;;;N;;;;; 10631;LINEAR A SIGN AB057;Lo;0;L;;;;;N;;;;; 10632;LINEAR A SIGN AB058;Lo;0;L;;;;;N;;;;; 10633;LINEAR A SIGN AB059;Lo;0;L;;;;;N;;;;; 10634;LINEAR A SIGN AB060;Lo;0;L;;;;;N;;;;; 10635;LINEAR A SIGN AB061;Lo;0;L;;;;;N;;;;; 10636;LINEAR A SIGN AB065;Lo;0;L;;;;;N;;;;; 10637;LINEAR A SIGN AB066;Lo;0;L;;;;;N;;;;; 10638;LINEAR A SIGN AB067;Lo;0;L;;;;;N;;;;; 10639;LINEAR A SIGN AB069;Lo;0;L;;;;;N;;;;; 1063A;LINEAR A SIGN AB070;Lo;0;L;;;;;N;;;;; 1063B;LINEAR A SIGN AB073;Lo;0;L;;;;;N;;;;; 1063C;LINEAR A SIGN AB074;Lo;0;L;;;;;N;;;;; 1063D;LINEAR A SIGN AB076;Lo;0;L;;;;;N;;;;; 1063E;LINEAR A SIGN AB077;Lo;0;L;;;;;N;;;;; 1063F;LINEAR A SIGN AB078;Lo;0;L;;;;;N;;;;; 10640;LINEAR A SIGN AB079;Lo;0;L;;;;;N;;;;; 10641;LINEAR A SIGN AB080;Lo;0;L;;;;;N;;;;; 10642;LINEAR A SIGN AB081;Lo;0;L;;;;;N;;;;; 10643;LINEAR A SIGN AB082;Lo;0;L;;;;;N;;;;; 10644;LINEAR A SIGN AB085;Lo;0;L;;;;;N;;;;; 10645;LINEAR A SIGN AB086;Lo;0;L;;;;;N;;;;; 10646;LINEAR A SIGN AB087;Lo;0;L;;;;;N;;;;; 10647;LINEAR A SIGN A100-102;Lo;0;L;;;;;N;;;;; 10648;LINEAR A SIGN AB118;Lo;0;L;;;;;N;;;;; 10649;LINEAR A SIGN AB120;Lo;0;L;;;;;N;;;;; 1064A;LINEAR A SIGN A120B;Lo;0;L;;;;;N;;;;; 1064B;LINEAR A SIGN AB122;Lo;0;L;;;;;N;;;;; 1064C;LINEAR A SIGN AB123;Lo;0;L;;;;;N;;;;; 1064D;LINEAR A SIGN AB131A;Lo;0;L;;;;;N;;;;; 1064E;LINEAR A SIGN AB131B;Lo;0;L;;;;;N;;;;; 1064F;LINEAR A SIGN A131C;Lo;0;L;;;;;N;;;;; 10650;LINEAR A SIGN AB164;Lo;0;L;;;;;N;;;;; 10651;LINEAR A SIGN AB171;Lo;0;L;;;;;N;;;;; 10652;LINEAR A SIGN AB180;Lo;0;L;;;;;N;;;;; 10653;LINEAR A SIGN AB188;Lo;0;L;;;;;N;;;;; 10654;LINEAR A SIGN AB191;Lo;0;L;;;;;N;;;;; 10655;LINEAR A SIGN A301;Lo;0;L;;;;;N;;;;; 10656;LINEAR A SIGN A302;Lo;0;L;;;;;N;;;;; 10657;LINEAR A SIGN A303;Lo;0;L;;;;;N;;;;; 10658;LINEAR A SIGN A304;Lo;0;L;;;;;N;;;;; 10659;LINEAR A SIGN A305;Lo;0;L;;;;;N;;;;; 1065A;LINEAR A SIGN A306;Lo;0;L;;;;;N;;;;; 1065B;LINEAR A SIGN A307;Lo;0;L;;;;;N;;;;; 1065C;LINEAR A SIGN A308;Lo;0;L;;;;;N;;;;; 1065D;LINEAR A SIGN A309A;Lo;0;L;;;;;N;;;;; 1065E;LINEAR A SIGN A309B;Lo;0;L;;;;;N;;;;; 1065F;LINEAR A SIGN A309C;Lo;0;L;;;;;N;;;;; 10660;LINEAR A SIGN A310;Lo;0;L;;;;;N;;;;; 10661;LINEAR A SIGN A311;Lo;0;L;;;;;N;;;;; 10662;LINEAR A SIGN A312;Lo;0;L;;;;;N;;;;; 10663;LINEAR A SIGN A313A;Lo;0;L;;;;;N;;;;; 10664;LINEAR A SIGN A313B;Lo;0;L;;;;;N;;;;; 10665;LINEAR A SIGN A313C;Lo;0;L;;;;;N;;;;; 10666;LINEAR A SIGN A314;Lo;0;L;;;;;N;;;;; 10667;LINEAR A SIGN A315;Lo;0;L;;;;;N;;;;; 10668;LINEAR A SIGN A316;Lo;0;L;;;;;N;;;;; 10669;LINEAR A SIGN A317;Lo;0;L;;;;;N;;;;; 1066A;LINEAR A SIGN A318;Lo;0;L;;;;;N;;;;; 1066B;LINEAR A SIGN A319;Lo;0;L;;;;;N;;;;; 1066C;LINEAR A SIGN A320;Lo;0;L;;;;;N;;;;; 1066D;LINEAR A SIGN A321;Lo;0;L;;;;;N;;;;; 1066E;LINEAR A SIGN A322;Lo;0;L;;;;;N;;;;; 1066F;LINEAR A SIGN A323;Lo;0;L;;;;;N;;;;; 10670;LINEAR A SIGN A324;Lo;0;L;;;;;N;;;;; 10671;LINEAR A SIGN A325;Lo;0;L;;;;;N;;;;; 10672;LINEAR A SIGN A326;Lo;0;L;;;;;N;;;;; 10673;LINEAR A SIGN A327;Lo;0;L;;;;;N;;;;; 10674;LINEAR A SIGN A328;Lo;0;L;;;;;N;;;;; 10675;LINEAR A SIGN A329;Lo;0;L;;;;;N;;;;; 10676;LINEAR A SIGN A330;Lo;0;L;;;;;N;;;;; 10677;LINEAR A SIGN A331;Lo;0;L;;;;;N;;;;; 10678;LINEAR A SIGN A332;Lo;0;L;;;;;N;;;;; 10679;LINEAR A SIGN A333;Lo;0;L;;;;;N;;;;; 1067A;LINEAR A SIGN A334;Lo;0;L;;;;;N;;;;; 1067B;LINEAR A SIGN A335;Lo;0;L;;;;;N;;;;; 1067C;LINEAR A SIGN A336;Lo;0;L;;;;;N;;;;; 1067D;LINEAR A SIGN A337;Lo;0;L;;;;;N;;;;; 1067E;LINEAR A SIGN A338;Lo;0;L;;;;;N;;;;; 1067F;LINEAR A SIGN A339;Lo;0;L;;;;;N;;;;; 10680;LINEAR A SIGN A340;Lo;0;L;;;;;N;;;;; 10681;LINEAR A SIGN A341;Lo;0;L;;;;;N;;;;; 10682;LINEAR A SIGN A342;Lo;0;L;;;;;N;;;;; 10683;LINEAR A SIGN A343;Lo;0;L;;;;;N;;;;; 10684;LINEAR A SIGN A344;Lo;0;L;;;;;N;;;;; 10685;LINEAR A SIGN A345;Lo;0;L;;;;;N;;;;; 10686;LINEAR A SIGN A346;Lo;0;L;;;;;N;;;;; 10687;LINEAR A SIGN A347;Lo;0;L;;;;;N;;;;; 10688;LINEAR A SIGN A348;Lo;0;L;;;;;N;;;;; 10689;LINEAR A SIGN A349;Lo;0;L;;;;;N;;;;; 1068A;LINEAR A SIGN A350;Lo;0;L;;;;;N;;;;; 1068B;LINEAR A SIGN A351;Lo;0;L;;;;;N;;;;; 1068C;LINEAR A SIGN A352;Lo;0;L;;;;;N;;;;; 1068D;LINEAR A SIGN A353;Lo;0;L;;;;;N;;;;; 1068E;LINEAR A SIGN A354;Lo;0;L;;;;;N;;;;; 1068F;LINEAR A SIGN A355;Lo;0;L;;;;;N;;;;; 10690;LINEAR A SIGN A356;Lo;0;L;;;;;N;;;;; 10691;LINEAR A SIGN A357;Lo;0;L;;;;;N;;;;; 10692;LINEAR A SIGN A358;Lo;0;L;;;;;N;;;;; 10693;LINEAR A SIGN A359;Lo;0;L;;;;;N;;;;; 10694;LINEAR A SIGN A360;Lo;0;L;;;;;N;;;;; 10695;LINEAR A SIGN A361;Lo;0;L;;;;;N;;;;; 10696;LINEAR A SIGN A362;Lo;0;L;;;;;N;;;;; 10697;LINEAR A SIGN A363;Lo;0;L;;;;;N;;;;; 10698;LINEAR A SIGN A364;Lo;0;L;;;;;N;;;;; 10699;LINEAR A SIGN A365;Lo;0;L;;;;;N;;;;; 1069A;LINEAR A SIGN A366;Lo;0;L;;;;;N;;;;; 1069B;LINEAR A SIGN A367;Lo;0;L;;;;;N;;;;; 1069C;LINEAR A SIGN A368;Lo;0;L;;;;;N;;;;; 1069D;LINEAR A SIGN A369;Lo;0;L;;;;;N;;;;; 1069E;LINEAR A SIGN A370;Lo;0;L;;;;;N;;;;; 1069F;LINEAR A SIGN A371;Lo;0;L;;;;;N;;;;; 106A0;LINEAR A SIGN A400-VAS;Lo;0;L;;;;;N;;;;; 106A1;LINEAR A SIGN A401-VAS;Lo;0;L;;;;;N;;;;; 106A2;LINEAR A SIGN A402-VAS;Lo;0;L;;;;;N;;;;; 106A3;LINEAR A SIGN A403-VAS;Lo;0;L;;;;;N;;;;; 106A4;LINEAR A SIGN A404-VAS;Lo;0;L;;;;;N;;;;; 106A5;LINEAR A SIGN A405-VAS;Lo;0;L;;;;;N;;;;; 106A6;LINEAR A SIGN A406-VAS;Lo;0;L;;;;;N;;;;; 106A7;LINEAR A SIGN A407-VAS;Lo;0;L;;;;;N;;;;; 106A8;LINEAR A SIGN A408-VAS;Lo;0;L;;;;;N;;;;; 106A9;LINEAR A SIGN A409-VAS;Lo;0;L;;;;;N;;;;; 106AA;LINEAR A SIGN A410-VAS;Lo;0;L;;;;;N;;;;; 106AB;LINEAR A SIGN A411-VAS;Lo;0;L;;;;;N;;;;; 106AC;LINEAR A SIGN A412-VAS;Lo;0;L;;;;;N;;;;; 106AD;LINEAR A SIGN A413-VAS;Lo;0;L;;;;;N;;;;; 106AE;LINEAR A SIGN A414-VAS;Lo;0;L;;;;;N;;;;; 106AF;LINEAR A SIGN A415-VAS;Lo;0;L;;;;;N;;;;; 106B0;LINEAR A SIGN A416-VAS;Lo;0;L;;;;;N;;;;; 106B1;LINEAR A SIGN A417-VAS;Lo;0;L;;;;;N;;;;; 106B2;LINEAR A SIGN A418-VAS;Lo;0;L;;;;;N;;;;; 106B3;LINEAR A SIGN A501;Lo;0;L;;;;;N;;;;; 106B4;LINEAR A SIGN A502;Lo;0;L;;;;;N;;;;; 106B5;LINEAR A SIGN A503;Lo;0;L;;;;;N;;;;; 106B6;LINEAR A SIGN A504;Lo;0;L;;;;;N;;;;; 106B7;LINEAR A SIGN A505;Lo;0;L;;;;;N;;;;; 106B8;LINEAR A SIGN A506;Lo;0;L;;;;;N;;;;; 106B9;LINEAR A SIGN A508;Lo;0;L;;;;;N;;;;; 106BA;LINEAR A SIGN A509;Lo;0;L;;;;;N;;;;; 106BB;LINEAR A SIGN A510;Lo;0;L;;;;;N;;;;; 106BC;LINEAR A SIGN A511;Lo;0;L;;;;;N;;;;; 106BD;LINEAR A SIGN A512;Lo;0;L;;;;;N;;;;; 106BE;LINEAR A SIGN A513;Lo;0;L;;;;;N;;;;; 106BF;LINEAR A SIGN A515;Lo;0;L;;;;;N;;;;; 106C0;LINEAR A SIGN A516;Lo;0;L;;;;;N;;;;; 106C1;LINEAR A SIGN A520;Lo;0;L;;;;;N;;;;; 106C2;LINEAR A SIGN A521;Lo;0;L;;;;;N;;;;; 106C3;LINEAR A SIGN A523;Lo;0;L;;;;;N;;;;; 106C4;LINEAR A SIGN A524;Lo;0;L;;;;;N;;;;; 106C5;LINEAR A SIGN A525;Lo;0;L;;;;;N;;;;; 106C6;LINEAR A SIGN A526;Lo;0;L;;;;;N;;;;; 106C7;LINEAR A SIGN A527;Lo;0;L;;;;;N;;;;; 106C8;LINEAR A SIGN A528;Lo;0;L;;;;;N;;;;; 106C9;LINEAR A SIGN A529;Lo;0;L;;;;;N;;;;; 106CA;LINEAR A SIGN A530;Lo;0;L;;;;;N;;;;; 106CB;LINEAR A SIGN A531;Lo;0;L;;;;;N;;;;; 106CC;LINEAR A SIGN A532;Lo;0;L;;;;;N;;;;; 106CD;LINEAR A SIGN A534;Lo;0;L;;;;;N;;;;; 106CE;LINEAR A SIGN A535;Lo;0;L;;;;;N;;;;; 106CF;LINEAR A SIGN A536;Lo;0;L;;;;;N;;;;; 106D0;LINEAR A SIGN A537;Lo;0;L;;;;;N;;;;; 106D1;LINEAR A SIGN A538;Lo;0;L;;;;;N;;;;; 106D2;LINEAR A SIGN A539;Lo;0;L;;;;;N;;;;; 106D3;LINEAR A SIGN A540;Lo;0;L;;;;;N;;;;; 106D4;LINEAR A SIGN A541;Lo;0;L;;;;;N;;;;; 106D5;LINEAR A SIGN A542;Lo;0;L;;;;;N;;;;; 106D6;LINEAR A SIGN A545;Lo;0;L;;;;;N;;;;; 106D7;LINEAR A SIGN A547;Lo;0;L;;;;;N;;;;; 106D8;LINEAR A SIGN A548;Lo;0;L;;;;;N;;;;; 106D9;LINEAR A SIGN A549;Lo;0;L;;;;;N;;;;; 106DA;LINEAR A SIGN A550;Lo;0;L;;;;;N;;;;; 106DB;LINEAR A SIGN A551;Lo;0;L;;;;;N;;;;; 106DC;LINEAR A SIGN A552;Lo;0;L;;;;;N;;;;; 106DD;LINEAR A SIGN A553;Lo;0;L;;;;;N;;;;; 106DE;LINEAR A SIGN A554;Lo;0;L;;;;;N;;;;; 106DF;LINEAR A SIGN A555;Lo;0;L;;;;;N;;;;; 106E0;LINEAR A SIGN A556;Lo;0;L;;;;;N;;;;; 106E1;LINEAR A SIGN A557;Lo;0;L;;;;;N;;;;; 106E2;LINEAR A SIGN A559;Lo;0;L;;;;;N;;;;; 106E3;LINEAR A SIGN A563;Lo;0;L;;;;;N;;;;; 106E4;LINEAR A SIGN A564;Lo;0;L;;;;;N;;;;; 106E5;LINEAR A SIGN A565;Lo;0;L;;;;;N;;;;; 106E6;LINEAR A SIGN A566;Lo;0;L;;;;;N;;;;; 106E7;LINEAR A SIGN A568;Lo;0;L;;;;;N;;;;; 106E8;LINEAR A SIGN A569;Lo;0;L;;;;;N;;;;; 106E9;LINEAR A SIGN A570;Lo;0;L;;;;;N;;;;; 106EA;LINEAR A SIGN A571;Lo;0;L;;;;;N;;;;; 106EB;LINEAR A SIGN A572;Lo;0;L;;;;;N;;;;; 106EC;LINEAR A SIGN A573;Lo;0;L;;;;;N;;;;; 106ED;LINEAR A SIGN A574;Lo;0;L;;;;;N;;;;; 106EE;LINEAR A SIGN A575;Lo;0;L;;;;;N;;;;; 106EF;LINEAR A SIGN A576;Lo;0;L;;;;;N;;;;; 106F0;LINEAR A SIGN A577;Lo;0;L;;;;;N;;;;; 106F1;LINEAR A SIGN A578;Lo;0;L;;;;;N;;;;; 106F2;LINEAR A SIGN A579;Lo;0;L;;;;;N;;;;; 106F3;LINEAR A SIGN A580;Lo;0;L;;;;;N;;;;; 106F4;LINEAR A SIGN A581;Lo;0;L;;;;;N;;;;; 106F5;LINEAR A SIGN A582;Lo;0;L;;;;;N;;;;; 106F6;LINEAR A SIGN A583;Lo;0;L;;;;;N;;;;; 106F7;LINEAR A SIGN A584;Lo;0;L;;;;;N;;;;; 106F8;LINEAR A SIGN A585;Lo;0;L;;;;;N;;;;; 106F9;LINEAR A SIGN A586;Lo;0;L;;;;;N;;;;; 106FA;LINEAR A SIGN A587;Lo;0;L;;;;;N;;;;; 106FB;LINEAR A SIGN A588;Lo;0;L;;;;;N;;;;; 106FC;LINEAR A SIGN A589;Lo;0;L;;;;;N;;;;; 106FD;LINEAR A SIGN A591;Lo;0;L;;;;;N;;;;; 106FE;LINEAR A SIGN A592;Lo;0;L;;;;;N;;;;; 106FF;LINEAR A SIGN A594;Lo;0;L;;;;;N;;;;; 10700;LINEAR A SIGN A595;Lo;0;L;;;;;N;;;;; 10701;LINEAR A SIGN A596;Lo;0;L;;;;;N;;;;; 10702;LINEAR A SIGN A598;Lo;0;L;;;;;N;;;;; 10703;LINEAR A SIGN A600;Lo;0;L;;;;;N;;;;; 10704;LINEAR A SIGN A601;Lo;0;L;;;;;N;;;;; 10705;LINEAR A SIGN A602;Lo;0;L;;;;;N;;;;; 10706;LINEAR A SIGN A603;Lo;0;L;;;;;N;;;;; 10707;LINEAR A SIGN A604;Lo;0;L;;;;;N;;;;; 10708;LINEAR A SIGN A606;Lo;0;L;;;;;N;;;;; 10709;LINEAR A SIGN A608;Lo;0;L;;;;;N;;;;; 1070A;LINEAR A SIGN A609;Lo;0;L;;;;;N;;;;; 1070B;LINEAR A SIGN A610;Lo;0;L;;;;;N;;;;; 1070C;LINEAR A SIGN A611;Lo;0;L;;;;;N;;;;; 1070D;LINEAR A SIGN A612;Lo;0;L;;;;;N;;;;; 1070E;LINEAR A SIGN A613;Lo;0;L;;;;;N;;;;; 1070F;LINEAR A SIGN A614;Lo;0;L;;;;;N;;;;; 10710;LINEAR A SIGN A615;Lo;0;L;;;;;N;;;;; 10711;LINEAR A SIGN A616;Lo;0;L;;;;;N;;;;; 10712;LINEAR A SIGN A617;Lo;0;L;;;;;N;;;;; 10713;LINEAR A SIGN A618;Lo;0;L;;;;;N;;;;; 10714;LINEAR A SIGN A619;Lo;0;L;;;;;N;;;;; 10715;LINEAR A SIGN A620;Lo;0;L;;;;;N;;;;; 10716;LINEAR A SIGN A621;Lo;0;L;;;;;N;;;;; 10717;LINEAR A SIGN A622;Lo;0;L;;;;;N;;;;; 10718;LINEAR A SIGN A623;Lo;0;L;;;;;N;;;;; 10719;LINEAR A SIGN A624;Lo;0;L;;;;;N;;;;; 1071A;LINEAR A SIGN A626;Lo;0;L;;;;;N;;;;; 1071B;LINEAR A SIGN A627;Lo;0;L;;;;;N;;;;; 1071C;LINEAR A SIGN A628;Lo;0;L;;;;;N;;;;; 1071D;LINEAR A SIGN A629;Lo;0;L;;;;;N;;;;; 1071E;LINEAR A SIGN A634;Lo;0;L;;;;;N;;;;; 1071F;LINEAR A SIGN A637;Lo;0;L;;;;;N;;;;; 10720;LINEAR A SIGN A638;Lo;0;L;;;;;N;;;;; 10721;LINEAR A SIGN A640;Lo;0;L;;;;;N;;;;; 10722;LINEAR A SIGN A642;Lo;0;L;;;;;N;;;;; 10723;LINEAR A SIGN A643;Lo;0;L;;;;;N;;;;; 10724;LINEAR A SIGN A644;Lo;0;L;;;;;N;;;;; 10725;LINEAR A SIGN A645;Lo;0;L;;;;;N;;;;; 10726;LINEAR A SIGN A646;Lo;0;L;;;;;N;;;;; 10727;LINEAR A SIGN A648;Lo;0;L;;;;;N;;;;; 10728;LINEAR A SIGN A649;Lo;0;L;;;;;N;;;;; 10729;LINEAR A SIGN A651;Lo;0;L;;;;;N;;;;; 1072A;LINEAR A SIGN A652;Lo;0;L;;;;;N;;;;; 1072B;LINEAR A SIGN A653;Lo;0;L;;;;;N;;;;; 1072C;LINEAR A SIGN A654;Lo;0;L;;;;;N;;;;; 1072D;LINEAR A SIGN A655;Lo;0;L;;;;;N;;;;; 1072E;LINEAR A SIGN A656;Lo;0;L;;;;;N;;;;; 1072F;LINEAR A SIGN A657;Lo;0;L;;;;;N;;;;; 10730;LINEAR A SIGN A658;Lo;0;L;;;;;N;;;;; 10731;LINEAR A SIGN A659;Lo;0;L;;;;;N;;;;; 10732;LINEAR A SIGN A660;Lo;0;L;;;;;N;;;;; 10733;LINEAR A SIGN A661;Lo;0;L;;;;;N;;;;; 10734;LINEAR A SIGN A662;Lo;0;L;;;;;N;;;;; 10735;LINEAR A SIGN A663;Lo;0;L;;;;;N;;;;; 10736;LINEAR A SIGN A664;Lo;0;L;;;;;N;;;;; 10740;LINEAR A SIGN A701 A;Lo;0;L;;;;;N;;;;; 10741;LINEAR A SIGN A702 B;Lo;0;L;;;;;N;;;;; 10742;LINEAR A SIGN A703 D;Lo;0;L;;;;;N;;;;; 10743;LINEAR A SIGN A704 E;Lo;0;L;;;;;N;;;;; 10744;LINEAR A SIGN A705 F;Lo;0;L;;;;;N;;;;; 10745;LINEAR A SIGN A706 H;Lo;0;L;;;;;N;;;;; 10746;LINEAR A SIGN A707 J;Lo;0;L;;;;;N;;;;; 10747;LINEAR A SIGN A708 K;Lo;0;L;;;;;N;;;;; 10748;LINEAR A SIGN A709 L;Lo;0;L;;;;;N;;;;; 10749;LINEAR A SIGN A709-2 L2;Lo;0;L;;;;;N;;;;; 1074A;LINEAR A SIGN A709-3 L3;Lo;0;L;;;;;N;;;;; 1074B;LINEAR A SIGN A709-4 L4;Lo;0;L;;;;;N;;;;; 1074C;LINEAR A SIGN A709-6 L6;Lo;0;L;;;;;N;;;;; 1074D;LINEAR A SIGN A710 W;Lo;0;L;;;;;N;;;;; 1074E;LINEAR A SIGN A711 X;Lo;0;L;;;;;N;;;;; 1074F;LINEAR A SIGN A712 Y;Lo;0;L;;;;;N;;;;; 10750;LINEAR A SIGN A713 OMEGA;Lo;0;L;;;;;N;;;;; 10751;LINEAR A SIGN A714 ABB;Lo;0;L;;;;;N;;;;; 10752;LINEAR A SIGN A715 BB;Lo;0;L;;;;;N;;;;; 10753;LINEAR A SIGN A717 DD;Lo;0;L;;;;;N;;;;; 10754;LINEAR A SIGN A726 EYYY;Lo;0;L;;;;;N;;;;; 10755;LINEAR A SIGN A732 JE;Lo;0;L;;;;;N;;;;; 10760;LINEAR A SIGN A800;Lo;0;L;;;;;N;;;;; 10761;LINEAR A SIGN A801;Lo;0;L;;;;;N;;;;; 10762;LINEAR A SIGN A802;Lo;0;L;;;;;N;;;;; 10763;LINEAR A SIGN A803;Lo;0;L;;;;;N;;;;; 10764;LINEAR A SIGN A804;Lo;0;L;;;;;N;;;;; 10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;; 10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;; 10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;; 10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; 10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; 10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; 10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;; 10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;; 10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;; 10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;; 1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;; 1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;; 1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;; 1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;; 1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;; 1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;; 10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;; 10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;; 10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;; 10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;; 10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;; 10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;; 10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;; 10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;; 10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;; 10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;; 1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;; 1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;; 1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;; 1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;; 1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;; 1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;; 10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;; 10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;; 10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;; 10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;; 10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;; 10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;; 10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;; 10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;; 10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;; 10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;; 1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;; 1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;; 1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;; 1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;; 1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;; 1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;; 10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;; 10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;; 10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;; 10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;; 10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;; 10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;; 10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;; 10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;; 1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;; 1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;; 10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; 10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; 10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;; 10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; 10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; 10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; 10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; 1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; 1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; 1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; 1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; 10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;; 10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; 10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; 10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; 10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; 10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; 10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;; 10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;; 10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;; 1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;; 1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;; 1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;; 1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; 10860;PALMYRENE LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10861;PALMYRENE LETTER BETH;Lo;0;R;;;;;N;;;;; 10862;PALMYRENE LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10863;PALMYRENE LETTER DALETH;Lo;0;R;;;;;N;;;;; 10864;PALMYRENE LETTER HE;Lo;0;R;;;;;N;;;;; 10865;PALMYRENE LETTER WAW;Lo;0;R;;;;;N;;;;; 10866;PALMYRENE LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10867;PALMYRENE LETTER HETH;Lo;0;R;;;;;N;;;;; 10868;PALMYRENE LETTER TETH;Lo;0;R;;;;;N;;;;; 10869;PALMYRENE LETTER YODH;Lo;0;R;;;;;N;;;;; 1086A;PALMYRENE LETTER KAPH;Lo;0;R;;;;;N;;;;; 1086B;PALMYRENE LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 1086C;PALMYRENE LETTER MEM;Lo;0;R;;;;;N;;;;; 1086D;PALMYRENE LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 1086E;PALMYRENE LETTER NUN;Lo;0;R;;;;;N;;;;; 1086F;PALMYRENE LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10870;PALMYRENE LETTER AYIN;Lo;0;R;;;;;N;;;;; 10871;PALMYRENE LETTER PE;Lo;0;R;;;;;N;;;;; 10872;PALMYRENE LETTER SADHE;Lo;0;R;;;;;N;;;;; 10873;PALMYRENE LETTER QOPH;Lo;0;R;;;;;N;;;;; 10874;PALMYRENE LETTER RESH;Lo;0;R;;;;;N;;;;; 10875;PALMYRENE LETTER SHIN;Lo;0;R;;;;;N;;;;; 10876;PALMYRENE LETTER TAW;Lo;0;R;;;;;N;;;;; 10877;PALMYRENE LEFT-POINTING FLEURON;So;0;R;;;;;N;;;;; 10878;PALMYRENE RIGHT-POINTING FLEURON;So;0;R;;;;;N;;;;; 10879;PALMYRENE NUMBER ONE;No;0;R;;;;1;N;;;;; 1087A;PALMYRENE NUMBER TWO;No;0;R;;;;2;N;;;;; 1087B;PALMYRENE NUMBER THREE;No;0;R;;;;3;N;;;;; 1087C;PALMYRENE NUMBER FOUR;No;0;R;;;;4;N;;;;; 1087D;PALMYRENE NUMBER FIVE;No;0;R;;;;5;N;;;;; 1087E;PALMYRENE NUMBER TEN;No;0;R;;;;10;N;;;;; 1087F;PALMYRENE NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10880;NABATAEAN LETTER FINAL ALEPH;Lo;0;R;;;;;N;;;;; 10881;NABATAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10882;NABATAEAN LETTER FINAL BETH;Lo;0;R;;;;;N;;;;; 10883;NABATAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10884;NABATAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10885;NABATAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10886;NABATAEAN LETTER FINAL HE;Lo;0;R;;;;;N;;;;; 10887;NABATAEAN LETTER HE;Lo;0;R;;;;;N;;;;; 10888;NABATAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10889;NABATAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 1088A;NABATAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; 1088B;NABATAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; 1088C;NABATAEAN LETTER FINAL YODH;Lo;0;R;;;;;N;;;;; 1088D;NABATAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; 1088E;NABATAEAN LETTER FINAL KAPH;Lo;0;R;;;;;N;;;;; 1088F;NABATAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10890;NABATAEAN LETTER FINAL LAMEDH;Lo;0;R;;;;;N;;;;; 10891;NABATAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10892;NABATAEAN LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 10893;NABATAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10894;NABATAEAN LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 10895;NABATAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10896;NABATAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10897;NABATAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10898;NABATAEAN LETTER PE;Lo;0;R;;;;;N;;;;; 10899;NABATAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 1089A;NABATAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 1089B;NABATAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; 1089C;NABATAEAN LETTER FINAL SHIN;Lo;0;R;;;;;N;;;;; 1089D;NABATAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 1089E;NABATAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; 108A7;NABATAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; 108A8;NABATAEAN NUMBER TWO;No;0;R;;;;2;N;;;;; 108A9;NABATAEAN NUMBER THREE;No;0;R;;;;3;N;;;;; 108AA;NABATAEAN NUMBER FOUR;No;0;R;;;;4;N;;;;; 108AB;NABATAEAN CRUCIFORM NUMBER FOUR;No;0;R;;;;4;N;;;;; 108AC;NABATAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 108AD;NABATAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; 108AE;NABATAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 108AF;NABATAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;; 10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;; 10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;; 10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;; 10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;; 10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;; 10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;; 10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;; 10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;; 1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;; 1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;; 1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;; 1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;; 10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;; 10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;; 10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;; 10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;; 10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;; 10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;; 10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;; 10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;; 10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;; 10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;; 10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;; 10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;; 10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;; 10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;; 10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;; 1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;; 1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;; 1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;; 1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;; 1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;; 1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;; 10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;; 10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;; 10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;; 10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;; 10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;; 10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;; 10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;; 10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;; 10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;; 10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;; 1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;; 10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;; 10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;; 10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;; 10983;MEROITIC HIEROGLYPHIC LETTER O;Lo;0;R;;;;;N;;;;; 10984;MEROITIC HIEROGLYPHIC LETTER YA;Lo;0;R;;;;;N;;;;; 10985;MEROITIC HIEROGLYPHIC LETTER WA;Lo;0;R;;;;;N;;;;; 10986;MEROITIC HIEROGLYPHIC LETTER BA;Lo;0;R;;;;;N;;;;; 10987;MEROITIC HIEROGLYPHIC LETTER BA-2;Lo;0;R;;;;;N;;;;; 10988;MEROITIC HIEROGLYPHIC LETTER PA;Lo;0;R;;;;;N;;;;; 10989;MEROITIC HIEROGLYPHIC LETTER MA;Lo;0;R;;;;;N;;;;; 1098A;MEROITIC HIEROGLYPHIC LETTER NA;Lo;0;R;;;;;N;;;;; 1098B;MEROITIC HIEROGLYPHIC LETTER NA-2;Lo;0;R;;;;;N;;;;; 1098C;MEROITIC HIEROGLYPHIC LETTER NE;Lo;0;R;;;;;N;;;;; 1098D;MEROITIC HIEROGLYPHIC LETTER NE-2;Lo;0;R;;;;;N;;;;; 1098E;MEROITIC HIEROGLYPHIC LETTER RA;Lo;0;R;;;;;N;;;;; 1098F;MEROITIC HIEROGLYPHIC LETTER RA-2;Lo;0;R;;;;;N;;;;; 10990;MEROITIC HIEROGLYPHIC LETTER LA;Lo;0;R;;;;;N;;;;; 10991;MEROITIC HIEROGLYPHIC LETTER KHA;Lo;0;R;;;;;N;;;;; 10992;MEROITIC HIEROGLYPHIC LETTER HHA;Lo;0;R;;;;;N;;;;; 10993;MEROITIC HIEROGLYPHIC LETTER SA;Lo;0;R;;;;;N;;;;; 10994;MEROITIC HIEROGLYPHIC LETTER SA-2;Lo;0;R;;;;;N;;;;; 10995;MEROITIC HIEROGLYPHIC LETTER SE;Lo;0;R;;;;;N;;;;; 10996;MEROITIC HIEROGLYPHIC LETTER KA;Lo;0;R;;;;;N;;;;; 10997;MEROITIC HIEROGLYPHIC LETTER QA;Lo;0;R;;;;;N;;;;; 10998;MEROITIC HIEROGLYPHIC LETTER TA;Lo;0;R;;;;;N;;;;; 10999;MEROITIC HIEROGLYPHIC LETTER TA-2;Lo;0;R;;;;;N;;;;; 1099A;MEROITIC HIEROGLYPHIC LETTER TE;Lo;0;R;;;;;N;;;;; 1099B;MEROITIC HIEROGLYPHIC LETTER TE-2;Lo;0;R;;;;;N;;;;; 1099C;MEROITIC HIEROGLYPHIC LETTER TO;Lo;0;R;;;;;N;;;;; 1099D;MEROITIC HIEROGLYPHIC LETTER DA;Lo;0;R;;;;;N;;;;; 1099E;MEROITIC HIEROGLYPHIC SYMBOL VIDJ;Lo;0;R;;;;;N;;;;; 1099F;MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2;Lo;0;R;;;;;N;;;;; 109A0;MEROITIC CURSIVE LETTER A;Lo;0;R;;;;;N;;;;; 109A1;MEROITIC CURSIVE LETTER E;Lo;0;R;;;;;N;;;;; 109A2;MEROITIC CURSIVE LETTER I;Lo;0;R;;;;;N;;;;; 109A3;MEROITIC CURSIVE LETTER O;Lo;0;R;;;;;N;;;;; 109A4;MEROITIC CURSIVE LETTER YA;Lo;0;R;;;;;N;;;;; 109A5;MEROITIC CURSIVE LETTER WA;Lo;0;R;;;;;N;;;;; 109A6;MEROITIC CURSIVE LETTER BA;Lo;0;R;;;;;N;;;;; 109A7;MEROITIC CURSIVE LETTER PA;Lo;0;R;;;;;N;;;;; 109A8;MEROITIC CURSIVE LETTER MA;Lo;0;R;;;;;N;;;;; 109A9;MEROITIC CURSIVE LETTER NA;Lo;0;R;;;;;N;;;;; 109AA;MEROITIC CURSIVE LETTER NE;Lo;0;R;;;;;N;;;;; 109AB;MEROITIC CURSIVE LETTER RA;Lo;0;R;;;;;N;;;;; 109AC;MEROITIC CURSIVE LETTER LA;Lo;0;R;;;;;N;;;;; 109AD;MEROITIC CURSIVE LETTER KHA;Lo;0;R;;;;;N;;;;; 109AE;MEROITIC CURSIVE LETTER HHA;Lo;0;R;;;;;N;;;;; 109AF;MEROITIC CURSIVE LETTER SA;Lo;0;R;;;;;N;;;;; 109B0;MEROITIC CURSIVE LETTER ARCHAIC SA;Lo;0;R;;;;;N;;;;; 109B1;MEROITIC CURSIVE LETTER SE;Lo;0;R;;;;;N;;;;; 109B2;MEROITIC CURSIVE LETTER KA;Lo;0;R;;;;;N;;;;; 109B3;MEROITIC CURSIVE LETTER QA;Lo;0;R;;;;;N;;;;; 109B4;MEROITIC CURSIVE LETTER TA;Lo;0;R;;;;;N;;;;; 109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;; 109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;; 109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;; 109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;; 109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;; 10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;; 10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; 10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;; 10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;; 10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;; 10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;; 10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;; 10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;; 10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;; 10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;; 10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;; 10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;; 10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;; 10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;; 10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;; 10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;; 10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;; 10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;; 10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;; 10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;; 10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;; 10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;; 10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;; 10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;; 10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;; 10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;; 10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;; 10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;; 10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;; 10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;; 10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;; 10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;; 10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;; 10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;; 10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;; 10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;; 10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;; 10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;; 10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;; 10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;; 10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;; 10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;; 10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;; 10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;; 10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;; 10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;; 10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;; 10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;; 10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;; 10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;; 10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;; 10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;; 10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;; 10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;; 10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;; 10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;; 10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; 10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;; 10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;; 10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;; 10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; 10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;; 10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;; 10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;; 10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; 10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;; 10A80;OLD NORTH ARABIAN LETTER HEH;Lo;0;R;;;;;N;;;;; 10A81;OLD NORTH ARABIAN LETTER LAM;Lo;0;R;;;;;N;;;;; 10A82;OLD NORTH ARABIAN LETTER HAH;Lo;0;R;;;;;N;;;;; 10A83;OLD NORTH ARABIAN LETTER MEEM;Lo;0;R;;;;;N;;;;; 10A84;OLD NORTH ARABIAN LETTER QAF;Lo;0;R;;;;;N;;;;; 10A85;OLD NORTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10A86;OLD NORTH ARABIAN LETTER ES-2;Lo;0;R;;;;;N;;;;; 10A87;OLD NORTH ARABIAN LETTER REH;Lo;0;R;;;;;N;;;;; 10A88;OLD NORTH ARABIAN LETTER BEH;Lo;0;R;;;;;N;;;;; 10A89;OLD NORTH ARABIAN LETTER TEH;Lo;0;R;;;;;N;;;;; 10A8A;OLD NORTH ARABIAN LETTER ES-1;Lo;0;R;;;;;N;;;;; 10A8B;OLD NORTH ARABIAN LETTER KAF;Lo;0;R;;;;;N;;;;; 10A8C;OLD NORTH ARABIAN LETTER NOON;Lo;0;R;;;;;N;;;;; 10A8D;OLD NORTH ARABIAN LETTER KHAH;Lo;0;R;;;;;N;;;;; 10A8E;OLD NORTH ARABIAN LETTER SAD;Lo;0;R;;;;;N;;;;; 10A8F;OLD NORTH ARABIAN LETTER ES-3;Lo;0;R;;;;;N;;;;; 10A90;OLD NORTH ARABIAN LETTER FEH;Lo;0;R;;;;;N;;;;; 10A91;OLD NORTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; 10A92;OLD NORTH ARABIAN LETTER AIN;Lo;0;R;;;;;N;;;;; 10A93;OLD NORTH ARABIAN LETTER DAD;Lo;0;R;;;;;N;;;;; 10A94;OLD NORTH ARABIAN LETTER GEEM;Lo;0;R;;;;;N;;;;; 10A95;OLD NORTH ARABIAN LETTER DAL;Lo;0;R;;;;;N;;;;; 10A96;OLD NORTH ARABIAN LETTER GHAIN;Lo;0;R;;;;;N;;;;; 10A97;OLD NORTH ARABIAN LETTER TAH;Lo;0;R;;;;;N;;;;; 10A98;OLD NORTH ARABIAN LETTER ZAIN;Lo;0;R;;;;;N;;;;; 10A99;OLD NORTH ARABIAN LETTER THAL;Lo;0;R;;;;;N;;;;; 10A9A;OLD NORTH ARABIAN LETTER YEH;Lo;0;R;;;;;N;;;;; 10A9B;OLD NORTH ARABIAN LETTER THEH;Lo;0;R;;;;;N;;;;; 10A9C;OLD NORTH ARABIAN LETTER ZAH;Lo;0;R;;;;;N;;;;; 10A9D;OLD NORTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10A9E;OLD NORTH ARABIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10A9F;OLD NORTH ARABIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10AC0;MANICHAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10AC1;MANICHAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10AC2;MANICHAEAN LETTER BHETH;Lo;0;R;;;;;N;;;;; 10AC3;MANICHAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10AC4;MANICHAEAN LETTER GHIMEL;Lo;0;R;;;;;N;;;;; 10AC5;MANICHAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10AC6;MANICHAEAN LETTER HE;Lo;0;R;;;;;N;;;;; 10AC7;MANICHAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10AC8;MANICHAEAN SIGN UD;So;0;R;;;;;N;;;;; 10AC9;MANICHAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10ACA;MANICHAEAN LETTER ZHAYIN;Lo;0;R;;;;;N;;;;; 10ACB;MANICHAEAN LETTER JAYIN;Lo;0;R;;;;;N;;;;; 10ACC;MANICHAEAN LETTER JHAYIN;Lo;0;R;;;;;N;;;;; 10ACD;MANICHAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10ACE;MANICHAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10ACF;MANICHAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10AD0;MANICHAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10AD1;MANICHAEAN LETTER XAPH;Lo;0;R;;;;;N;;;;; 10AD2;MANICHAEAN LETTER KHAPH;Lo;0;R;;;;;N;;;;; 10AD3;MANICHAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10AD4;MANICHAEAN LETTER DHAMEDH;Lo;0;R;;;;;N;;;;; 10AD5;MANICHAEAN LETTER THAMEDH;Lo;0;R;;;;;N;;;;; 10AD6;MANICHAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10AD7;MANICHAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10AD8;MANICHAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10AD9;MANICHAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10ADA;MANICHAEAN LETTER AAYIN;Lo;0;R;;;;;N;;;;; 10ADB;MANICHAEAN LETTER PE;Lo;0;R;;;;;N;;;;; 10ADC;MANICHAEAN LETTER FE;Lo;0;R;;;;;N;;;;; 10ADD;MANICHAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10ADE;MANICHAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10ADF;MANICHAEAN LETTER XOPH;Lo;0;R;;;;;N;;;;; 10AE0;MANICHAEAN LETTER QHOPH;Lo;0;R;;;;;N;;;;; 10AE1;MANICHAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10AE2;MANICHAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10AE3;MANICHAEAN LETTER SSHIN;Lo;0;R;;;;;N;;;;; 10AE4;MANICHAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10AE5;MANICHAEAN ABBREVIATION MARK ABOVE;Mn;230;NSM;;;;;N;;;;; 10AE6;MANICHAEAN ABBREVIATION MARK BELOW;Mn;220;NSM;;;;;N;;;;; 10AEB;MANICHAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10AEC;MANICHAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 10AED;MANICHAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10AEE;MANICHAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10AEF;MANICHAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10AF0;MANICHAEAN PUNCTUATION STAR;Po;0;R;;;;;N;;;;; 10AF1;MANICHAEAN PUNCTUATION FLEURON;Po;0;R;;;;;N;;;;; 10AF2;MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT;Po;0;R;;;;;N;;;;; 10AF3;MANICHAEAN PUNCTUATION DOT WITHIN DOT;Po;0;R;;;;;N;;;;; 10AF4;MANICHAEAN PUNCTUATION DOT;Po;0;R;;;;;N;;;;; 10AF5;MANICHAEAN PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; 10AF6;MANICHAEAN PUNCTUATION LINE FILLER;Po;0;R;;;;;N;;;;; 10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;; 10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;; 10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;; 10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;; 10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;; 10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;; 10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;; 10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;; 10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;; 10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;; 10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;; 10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;; 10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;; 10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;; 10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;; 10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;; 10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;; 10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;; 10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;; 10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;; 10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;; 10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;; 10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;; 10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;; 10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;; 10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;; 10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;; 10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;; 10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;; 10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;; 10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;; 10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;; 10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;; 10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;; 10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;; 10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;; 10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;; 10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;; 10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;; 10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;; 10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;; 10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;; 10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;; 10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;; 10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;; 10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;; 10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;; 10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;; 10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;; 10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;; 10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;; 10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;; 10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;; 10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; 10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; 10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; 10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; 10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;; 10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; 10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; 10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; 10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; 10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; 10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; 10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; 10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; 10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; 10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10B80;PSALTER PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B81;PSALTER PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; 10B82;PSALTER PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B83;PSALTER PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B84;PSALTER PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; 10B85;PSALTER PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; 10B86;PSALTER PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B87;PSALTER PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; 10B88;PSALTER PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; 10B89;PSALTER PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B8A;PSALTER PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B8B;PSALTER PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; 10B8C;PSALTER PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; 10B8D;PSALTER PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B8E;PSALTER PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; 10B8F;PSALTER PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B90;PSALTER PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B91;PSALTER PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; 10B99;PSALTER PAHLAVI SECTION MARK;Po;0;R;;;;;N;;;;; 10B9A;PSALTER PAHLAVI TURNED SECTION MARK;Po;0;R;;;;;N;;;;; 10B9B;PSALTER PAHLAVI FOUR DOTS WITH CROSS;Po;0;R;;;;;N;;;;; 10B9C;PSALTER PAHLAVI FOUR DOTS WITH DOT;Po;0;R;;;;;N;;;;; 10BA9;PSALTER PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; 10BAA;PSALTER PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; 10BAB;PSALTER PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; 10BAC;PSALTER PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; 10BAD;PSALTER PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; 10BAE;PSALTER PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10BAF;PSALTER PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;; 10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;; 10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;; 10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;; 10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;; 10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;; 10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;; 10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;; 10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;; 10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;; 10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;; 10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;; 10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;; 10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;; 10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;; 10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;; 10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;; 10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;; 10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;; 10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;; 10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;; 10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;; 10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;; 10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;; 10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;; 10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;; 10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;; 10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;; 10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;; 10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;; 10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;; 10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;; 10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;; 10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;; 10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;; 10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;; 10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;; 10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;; 10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;; 10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;; 10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;; 10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;; 10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;; 10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;; 10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;; 10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;; 10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;; 10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;; 10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;; 10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;; 10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;; 10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;; 10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;; 10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;; 10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;; 10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;; 10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;; 10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;; 10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;; 10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;; 10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;; 10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;; 10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;; 10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;; 10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;; 10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;; 10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;; 10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;; 10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;; 10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;; 10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;; 10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;; 10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;; 10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;; 10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;; 10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;; 10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;; 10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;; 10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;; 10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;; 10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;; 10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;; 10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;; 10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;; 10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;; 10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;; 10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;; 10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;; 10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;; 10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;; 10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;; 10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;; 10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;; 10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;; 10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;; 10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;; 10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;; 10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;; 10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;; 10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;; 10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;; 10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; 10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; 10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; 11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;; 11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;; 11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;; 11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;; 11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;; 1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;; 1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;; 11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;; 11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;; 11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;; 11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;; 11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;; 11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;; 11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;; 11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;; 11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;; 11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;; 1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;; 1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;; 1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;; 1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;; 1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;; 1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;; 11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;; 11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;; 11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;; 11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;; 11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;; 11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;; 11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;; 11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;; 11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;; 1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;; 1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;; 1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;; 1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;; 1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;; 1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;; 11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;; 11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;; 11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;; 11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;; 11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;; 11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;; 11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;; 11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;; 11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;; 1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;; 11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;; 11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; 1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; 1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;; 1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;; 1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;; 11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;; 11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;; 11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;; 11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;; 11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;; 11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;; 11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;; 11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;; 1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;; 1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;; 1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;; 1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;; 1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;; 11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;; 11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;; 11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;; 11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;; 11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;; 11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;; 11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;; 11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;; 11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;; 11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;; 11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;; 11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;; 11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;; 11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;; 1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;; 1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;; 1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;; 1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;; 1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;; 1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;; 11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;; 11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;; 11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;; 11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;; 11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;; 11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;; 11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;; 11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;; 11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;; 1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;; 1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;; 1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;; 1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;; 1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;; 110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;; 110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;; 110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;; 110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;; 110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;; 110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;; 110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;; 110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;; 110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;; 110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;; 110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;; 110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;; 110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;; 110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;; 110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;; 110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;; 110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;; 110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;; 110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;; 110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; 110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;; 110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;; 110D2;SORA SOMPENG LETTER BAH;Lo;0;L;;;;;N;;;;; 110D3;SORA SOMPENG LETTER CAH;Lo;0;L;;;;;N;;;;; 110D4;SORA SOMPENG LETTER DAH;Lo;0;L;;;;;N;;;;; 110D5;SORA SOMPENG LETTER GAH;Lo;0;L;;;;;N;;;;; 110D6;SORA SOMPENG LETTER MAH;Lo;0;L;;;;;N;;;;; 110D7;SORA SOMPENG LETTER NGAH;Lo;0;L;;;;;N;;;;; 110D8;SORA SOMPENG LETTER LAH;Lo;0;L;;;;;N;;;;; 110D9;SORA SOMPENG LETTER NAH;Lo;0;L;;;;;N;;;;; 110DA;SORA SOMPENG LETTER VAH;Lo;0;L;;;;;N;;;;; 110DB;SORA SOMPENG LETTER PAH;Lo;0;L;;;;;N;;;;; 110DC;SORA SOMPENG LETTER YAH;Lo;0;L;;;;;N;;;;; 110DD;SORA SOMPENG LETTER RAH;Lo;0;L;;;;;N;;;;; 110DE;SORA SOMPENG LETTER HAH;Lo;0;L;;;;;N;;;;; 110DF;SORA SOMPENG LETTER KAH;Lo;0;L;;;;;N;;;;; 110E0;SORA SOMPENG LETTER JAH;Lo;0;L;;;;;N;;;;; 110E1;SORA SOMPENG LETTER NYAH;Lo;0;L;;;;;N;;;;; 110E2;SORA SOMPENG LETTER AH;Lo;0;L;;;;;N;;;;; 110E3;SORA SOMPENG LETTER EEH;Lo;0;L;;;;;N;;;;; 110E4;SORA SOMPENG LETTER IH;Lo;0;L;;;;;N;;;;; 110E5;SORA SOMPENG LETTER UH;Lo;0;L;;;;;N;;;;; 110E6;SORA SOMPENG LETTER OH;Lo;0;L;;;;;N;;;;; 110E7;SORA SOMPENG LETTER EH;Lo;0;L;;;;;N;;;;; 110E8;SORA SOMPENG LETTER MAE;Lo;0;L;;;;;N;;;;; 110F0;SORA SOMPENG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 110F1;SORA SOMPENG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 110F2;SORA SOMPENG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 110F3;SORA SOMPENG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 110F4;SORA SOMPENG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 110F5;SORA SOMPENG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 110F6;SORA SOMPENG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 110F7;SORA SOMPENG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 110F8;SORA SOMPENG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 110F9;SORA SOMPENG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11100;CHAKMA SIGN CANDRABINDU;Mn;230;NSM;;;;;N;;;;; 11101;CHAKMA SIGN ANUSVARA;Mn;230;NSM;;;;;N;;;;; 11102;CHAKMA SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; 11103;CHAKMA LETTER AA;Lo;0;L;;;;;N;;;;; 11104;CHAKMA LETTER I;Lo;0;L;;;;;N;;;;; 11105;CHAKMA LETTER U;Lo;0;L;;;;;N;;;;; 11106;CHAKMA LETTER E;Lo;0;L;;;;;N;;;;; 11107;CHAKMA LETTER KAA;Lo;0;L;;;;;N;;;;; 11108;CHAKMA LETTER KHAA;Lo;0;L;;;;;N;;;;; 11109;CHAKMA LETTER GAA;Lo;0;L;;;;;N;;;;; 1110A;CHAKMA LETTER GHAA;Lo;0;L;;;;;N;;;;; 1110B;CHAKMA LETTER NGAA;Lo;0;L;;;;;N;;;;; 1110C;CHAKMA LETTER CAA;Lo;0;L;;;;;N;;;;; 1110D;CHAKMA LETTER CHAA;Lo;0;L;;;;;N;;;;; 1110E;CHAKMA LETTER JAA;Lo;0;L;;;;;N;;;;; 1110F;CHAKMA LETTER JHAA;Lo;0;L;;;;;N;;;;; 11110;CHAKMA LETTER NYAA;Lo;0;L;;;;;N;;;;; 11111;CHAKMA LETTER TTAA;Lo;0;L;;;;;N;;;;; 11112;CHAKMA LETTER TTHAA;Lo;0;L;;;;;N;;;;; 11113;CHAKMA LETTER DDAA;Lo;0;L;;;;;N;;;;; 11114;CHAKMA LETTER DDHAA;Lo;0;L;;;;;N;;;;; 11115;CHAKMA LETTER NNAA;Lo;0;L;;;;;N;;;;; 11116;CHAKMA LETTER TAA;Lo;0;L;;;;;N;;;;; 11117;CHAKMA LETTER THAA;Lo;0;L;;;;;N;;;;; 11118;CHAKMA LETTER DAA;Lo;0;L;;;;;N;;;;; 11119;CHAKMA LETTER DHAA;Lo;0;L;;;;;N;;;;; 1111A;CHAKMA LETTER NAA;Lo;0;L;;;;;N;;;;; 1111B;CHAKMA LETTER PAA;Lo;0;L;;;;;N;;;;; 1111C;CHAKMA LETTER PHAA;Lo;0;L;;;;;N;;;;; 1111D;CHAKMA LETTER BAA;Lo;0;L;;;;;N;;;;; 1111E;CHAKMA LETTER BHAA;Lo;0;L;;;;;N;;;;; 1111F;CHAKMA LETTER MAA;Lo;0;L;;;;;N;;;;; 11120;CHAKMA LETTER YYAA;Lo;0;L;;;;;N;;;;; 11121;CHAKMA LETTER YAA;Lo;0;L;;;;;N;;;;; 11122;CHAKMA LETTER RAA;Lo;0;L;;;;;N;;;;; 11123;CHAKMA LETTER LAA;Lo;0;L;;;;;N;;;;; 11124;CHAKMA LETTER WAA;Lo;0;L;;;;;N;;;;; 11125;CHAKMA LETTER SAA;Lo;0;L;;;;;N;;;;; 11126;CHAKMA LETTER HAA;Lo;0;L;;;;;N;;;;; 11127;CHAKMA VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; 11128;CHAKMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 11129;CHAKMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1112A;CHAKMA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1112B;CHAKMA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1112C;CHAKMA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1112D;CHAKMA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1112E;CHAKMA VOWEL SIGN O;Mn;0;NSM;11131 11127;;;;N;;;;; 1112F;CHAKMA VOWEL SIGN AU;Mn;0;NSM;11132 11127;;;;N;;;;; 11130;CHAKMA VOWEL SIGN OI;Mn;0;NSM;;;;;N;;;;; 11131;CHAKMA O MARK;Mn;0;NSM;;;;;N;;;;; 11132;CHAKMA AU MARK;Mn;0;NSM;;;;;N;;;;; 11133;CHAKMA VIRAMA;Mn;9;NSM;;;;;N;;;;; 11134;CHAKMA MAAYYAA;Mn;9;NSM;;;;;N;;;;; 11136;CHAKMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11137;CHAKMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11138;CHAKMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11139;CHAKMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1113A;CHAKMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1113B;CHAKMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1113C;CHAKMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1113D;CHAKMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1113E;CHAKMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1113F;CHAKMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11140;CHAKMA SECTION MARK;Po;0;L;;;;;N;;;;; 11141;CHAKMA DANDA;Po;0;L;;;;;N;;;;; 11142;CHAKMA DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11143;CHAKMA QUESTION MARK;Po;0;L;;;;;N;;;;; 11150;MAHAJANI LETTER A;Lo;0;L;;;;;N;;;;; 11151;MAHAJANI LETTER I;Lo;0;L;;;;;N;;;;; 11152;MAHAJANI LETTER U;Lo;0;L;;;;;N;;;;; 11153;MAHAJANI LETTER E;Lo;0;L;;;;;N;;;;; 11154;MAHAJANI LETTER O;Lo;0;L;;;;;N;;;;; 11155;MAHAJANI LETTER KA;Lo;0;L;;;;;N;;;;; 11156;MAHAJANI LETTER KHA;Lo;0;L;;;;;N;;;;; 11157;MAHAJANI LETTER GA;Lo;0;L;;;;;N;;;;; 11158;MAHAJANI LETTER GHA;Lo;0;L;;;;;N;;;;; 11159;MAHAJANI LETTER CA;Lo;0;L;;;;;N;;;;; 1115A;MAHAJANI LETTER CHA;Lo;0;L;;;;;N;;;;; 1115B;MAHAJANI LETTER JA;Lo;0;L;;;;;N;;;;; 1115C;MAHAJANI LETTER JHA;Lo;0;L;;;;;N;;;;; 1115D;MAHAJANI LETTER NYA;Lo;0;L;;;;;N;;;;; 1115E;MAHAJANI LETTER TTA;Lo;0;L;;;;;N;;;;; 1115F;MAHAJANI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11160;MAHAJANI LETTER DDA;Lo;0;L;;;;;N;;;;; 11161;MAHAJANI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11162;MAHAJANI LETTER NNA;Lo;0;L;;;;;N;;;;; 11163;MAHAJANI LETTER TA;Lo;0;L;;;;;N;;;;; 11164;MAHAJANI LETTER THA;Lo;0;L;;;;;N;;;;; 11165;MAHAJANI LETTER DA;Lo;0;L;;;;;N;;;;; 11166;MAHAJANI LETTER DHA;Lo;0;L;;;;;N;;;;; 11167;MAHAJANI LETTER NA;Lo;0;L;;;;;N;;;;; 11168;MAHAJANI LETTER PA;Lo;0;L;;;;;N;;;;; 11169;MAHAJANI LETTER PHA;Lo;0;L;;;;;N;;;;; 1116A;MAHAJANI LETTER BA;Lo;0;L;;;;;N;;;;; 1116B;MAHAJANI LETTER BHA;Lo;0;L;;;;;N;;;;; 1116C;MAHAJANI LETTER MA;Lo;0;L;;;;;N;;;;; 1116D;MAHAJANI LETTER RA;Lo;0;L;;;;;N;;;;; 1116E;MAHAJANI LETTER LA;Lo;0;L;;;;;N;;;;; 1116F;MAHAJANI LETTER VA;Lo;0;L;;;;;N;;;;; 11170;MAHAJANI LETTER SA;Lo;0;L;;;;;N;;;;; 11171;MAHAJANI LETTER HA;Lo;0;L;;;;;N;;;;; 11172;MAHAJANI LETTER RRA;Lo;0;L;;;;;N;;;;; 11173;MAHAJANI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 11174;MAHAJANI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 11175;MAHAJANI SECTION MARK;Po;0;L;;;;;N;;;;; 11176;MAHAJANI LIGATURE SHRI;Lo;0;L;;;;;N;;;;; 11180;SHARADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11181;SHARADA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11182;SHARADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11183;SHARADA LETTER A;Lo;0;L;;;;;N;;;;; 11184;SHARADA LETTER AA;Lo;0;L;;;;;N;;;;; 11185;SHARADA LETTER I;Lo;0;L;;;;;N;;;;; 11186;SHARADA LETTER II;Lo;0;L;;;;;N;;;;; 11187;SHARADA LETTER U;Lo;0;L;;;;;N;;;;; 11188;SHARADA LETTER UU;Lo;0;L;;;;;N;;;;; 11189;SHARADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1118A;SHARADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1118B;SHARADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1118C;SHARADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1118D;SHARADA LETTER E;Lo;0;L;;;;;N;;;;; 1118E;SHARADA LETTER AI;Lo;0;L;;;;;N;;;;; 1118F;SHARADA LETTER O;Lo;0;L;;;;;N;;;;; 11190;SHARADA LETTER AU;Lo;0;L;;;;;N;;;;; 11191;SHARADA LETTER KA;Lo;0;L;;;;;N;;;;; 11192;SHARADA LETTER KHA;Lo;0;L;;;;;N;;;;; 11193;SHARADA LETTER GA;Lo;0;L;;;;;N;;;;; 11194;SHARADA LETTER GHA;Lo;0;L;;;;;N;;;;; 11195;SHARADA LETTER NGA;Lo;0;L;;;;;N;;;;; 11196;SHARADA LETTER CA;Lo;0;L;;;;;N;;;;; 11197;SHARADA LETTER CHA;Lo;0;L;;;;;N;;;;; 11198;SHARADA LETTER JA;Lo;0;L;;;;;N;;;;; 11199;SHARADA LETTER JHA;Lo;0;L;;;;;N;;;;; 1119A;SHARADA LETTER NYA;Lo;0;L;;;;;N;;;;; 1119B;SHARADA LETTER TTA;Lo;0;L;;;;;N;;;;; 1119C;SHARADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1119D;SHARADA LETTER DDA;Lo;0;L;;;;;N;;;;; 1119E;SHARADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 1119F;SHARADA LETTER NNA;Lo;0;L;;;;;N;;;;; 111A0;SHARADA LETTER TA;Lo;0;L;;;;;N;;;;; 111A1;SHARADA LETTER THA;Lo;0;L;;;;;N;;;;; 111A2;SHARADA LETTER DA;Lo;0;L;;;;;N;;;;; 111A3;SHARADA LETTER DHA;Lo;0;L;;;;;N;;;;; 111A4;SHARADA LETTER NA;Lo;0;L;;;;;N;;;;; 111A5;SHARADA LETTER PA;Lo;0;L;;;;;N;;;;; 111A6;SHARADA LETTER PHA;Lo;0;L;;;;;N;;;;; 111A7;SHARADA LETTER BA;Lo;0;L;;;;;N;;;;; 111A8;SHARADA LETTER BHA;Lo;0;L;;;;;N;;;;; 111A9;SHARADA LETTER MA;Lo;0;L;;;;;N;;;;; 111AA;SHARADA LETTER YA;Lo;0;L;;;;;N;;;;; 111AB;SHARADA LETTER RA;Lo;0;L;;;;;N;;;;; 111AC;SHARADA LETTER LA;Lo;0;L;;;;;N;;;;; 111AD;SHARADA LETTER LLA;Lo;0;L;;;;;N;;;;; 111AE;SHARADA LETTER VA;Lo;0;L;;;;;N;;;;; 111AF;SHARADA LETTER SHA;Lo;0;L;;;;;N;;;;; 111B0;SHARADA LETTER SSA;Lo;0;L;;;;;N;;;;; 111B1;SHARADA LETTER SA;Lo;0;L;;;;;N;;;;; 111B2;SHARADA LETTER HA;Lo;0;L;;;;;N;;;;; 111B3;SHARADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 111B4;SHARADA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 111B5;SHARADA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 111B6;SHARADA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 111B7;SHARADA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 111B8;SHARADA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 111B9;SHARADA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 111BA;SHARADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 111BB;SHARADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 111BC;SHARADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 111BD;SHARADA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 111BE;SHARADA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 111BF;SHARADA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 111C0;SHARADA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 111C1;SHARADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 111C2;SHARADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 111C3;SHARADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 111C4;SHARADA OM;Lo;0;L;;;;;N;;;;; 111C5;SHARADA DANDA;Po;0;L;;;;;N;;;;; 111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;; 111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;; 111CD;SHARADA SUTRA MARK;Po;0;L;;;;;N;;;;; 111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 111D2;SHARADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 111D3;SHARADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 111D4;SHARADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 111D5;SHARADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 111D6;SHARADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 111D7;SHARADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 111DA;SHARADA EKAM;Lo;0;L;;;;;N;;;;; 111E1;SINHALA ARCHAIC DIGIT ONE;No;0;L;;;;1;N;;;;; 111E2;SINHALA ARCHAIC DIGIT TWO;No;0;L;;;;2;N;;;;; 111E3;SINHALA ARCHAIC DIGIT THREE;No;0;L;;;;3;N;;;;; 111E4;SINHALA ARCHAIC DIGIT FOUR;No;0;L;;;;4;N;;;;; 111E5;SINHALA ARCHAIC DIGIT FIVE;No;0;L;;;;5;N;;;;; 111E6;SINHALA ARCHAIC DIGIT SIX;No;0;L;;;;6;N;;;;; 111E7;SINHALA ARCHAIC DIGIT SEVEN;No;0;L;;;;7;N;;;;; 111E8;SINHALA ARCHAIC DIGIT EIGHT;No;0;L;;;;8;N;;;;; 111E9;SINHALA ARCHAIC DIGIT NINE;No;0;L;;;;9;N;;;;; 111EA;SINHALA ARCHAIC NUMBER TEN;No;0;L;;;;10;N;;;;; 111EB;SINHALA ARCHAIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 111EC;SINHALA ARCHAIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 111ED;SINHALA ARCHAIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 111EE;SINHALA ARCHAIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 111EF;SINHALA ARCHAIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 111F0;SINHALA ARCHAIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 111F1;SINHALA ARCHAIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 111F2;SINHALA ARCHAIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 111F3;SINHALA ARCHAIC NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 111F4;SINHALA ARCHAIC NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 11200;KHOJKI LETTER A;Lo;0;L;;;;;N;;;;; 11201;KHOJKI LETTER AA;Lo;0;L;;;;;N;;;;; 11202;KHOJKI LETTER I;Lo;0;L;;;;;N;;;;; 11203;KHOJKI LETTER U;Lo;0;L;;;;;N;;;;; 11204;KHOJKI LETTER E;Lo;0;L;;;;;N;;;;; 11205;KHOJKI LETTER AI;Lo;0;L;;;;;N;;;;; 11206;KHOJKI LETTER O;Lo;0;L;;;;;N;;;;; 11207;KHOJKI LETTER AU;Lo;0;L;;;;;N;;;;; 11208;KHOJKI LETTER KA;Lo;0;L;;;;;N;;;;; 11209;KHOJKI LETTER KHA;Lo;0;L;;;;;N;;;;; 1120A;KHOJKI LETTER GA;Lo;0;L;;;;;N;;;;; 1120B;KHOJKI LETTER GGA;Lo;0;L;;;;;N;;;;; 1120C;KHOJKI LETTER GHA;Lo;0;L;;;;;N;;;;; 1120D;KHOJKI LETTER NGA;Lo;0;L;;;;;N;;;;; 1120E;KHOJKI LETTER CA;Lo;0;L;;;;;N;;;;; 1120F;KHOJKI LETTER CHA;Lo;0;L;;;;;N;;;;; 11210;KHOJKI LETTER JA;Lo;0;L;;;;;N;;;;; 11211;KHOJKI LETTER JJA;Lo;0;L;;;;;N;;;;; 11213;KHOJKI LETTER NYA;Lo;0;L;;;;;N;;;;; 11214;KHOJKI LETTER TTA;Lo;0;L;;;;;N;;;;; 11215;KHOJKI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11216;KHOJKI LETTER DDA;Lo;0;L;;;;;N;;;;; 11217;KHOJKI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11218;KHOJKI LETTER NNA;Lo;0;L;;;;;N;;;;; 11219;KHOJKI LETTER TA;Lo;0;L;;;;;N;;;;; 1121A;KHOJKI LETTER THA;Lo;0;L;;;;;N;;;;; 1121B;KHOJKI LETTER DA;Lo;0;L;;;;;N;;;;; 1121C;KHOJKI LETTER DDDA;Lo;0;L;;;;;N;;;;; 1121D;KHOJKI LETTER DHA;Lo;0;L;;;;;N;;;;; 1121E;KHOJKI LETTER NA;Lo;0;L;;;;;N;;;;; 1121F;KHOJKI LETTER PA;Lo;0;L;;;;;N;;;;; 11220;KHOJKI LETTER PHA;Lo;0;L;;;;;N;;;;; 11221;KHOJKI LETTER BA;Lo;0;L;;;;;N;;;;; 11222;KHOJKI LETTER BBA;Lo;0;L;;;;;N;;;;; 11223;KHOJKI LETTER BHA;Lo;0;L;;;;;N;;;;; 11224;KHOJKI LETTER MA;Lo;0;L;;;;;N;;;;; 11225;KHOJKI LETTER YA;Lo;0;L;;;;;N;;;;; 11226;KHOJKI LETTER RA;Lo;0;L;;;;;N;;;;; 11227;KHOJKI LETTER LA;Lo;0;L;;;;;N;;;;; 11228;KHOJKI LETTER VA;Lo;0;L;;;;;N;;;;; 11229;KHOJKI LETTER SA;Lo;0;L;;;;;N;;;;; 1122A;KHOJKI LETTER HA;Lo;0;L;;;;;N;;;;; 1122B;KHOJKI LETTER LLA;Lo;0;L;;;;;N;;;;; 1122C;KHOJKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1122D;KHOJKI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1122E;KHOJKI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 1122F;KHOJKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11230;KHOJKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11231;KHOJKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11232;KHOJKI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11233;KHOJKI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 11234;KHOJKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11235;KHOJKI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 11236;KHOJKI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 11237;KHOJKI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; 11238;KHOJKI DANDA;Po;0;L;;;;;N;;;;; 11239;KHOJKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 1123A;KHOJKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; 1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;; 1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 112B0;KHUDAWADI LETTER A;Lo;0;L;;;;;N;;;;; 112B1;KHUDAWADI LETTER AA;Lo;0;L;;;;;N;;;;; 112B2;KHUDAWADI LETTER I;Lo;0;L;;;;;N;;;;; 112B3;KHUDAWADI LETTER II;Lo;0;L;;;;;N;;;;; 112B4;KHUDAWADI LETTER U;Lo;0;L;;;;;N;;;;; 112B5;KHUDAWADI LETTER UU;Lo;0;L;;;;;N;;;;; 112B6;KHUDAWADI LETTER E;Lo;0;L;;;;;N;;;;; 112B7;KHUDAWADI LETTER AI;Lo;0;L;;;;;N;;;;; 112B8;KHUDAWADI LETTER O;Lo;0;L;;;;;N;;;;; 112B9;KHUDAWADI LETTER AU;Lo;0;L;;;;;N;;;;; 112BA;KHUDAWADI LETTER KA;Lo;0;L;;;;;N;;;;; 112BB;KHUDAWADI LETTER KHA;Lo;0;L;;;;;N;;;;; 112BC;KHUDAWADI LETTER GA;Lo;0;L;;;;;N;;;;; 112BD;KHUDAWADI LETTER GGA;Lo;0;L;;;;;N;;;;; 112BE;KHUDAWADI LETTER GHA;Lo;0;L;;;;;N;;;;; 112BF;KHUDAWADI LETTER NGA;Lo;0;L;;;;;N;;;;; 112C0;KHUDAWADI LETTER CA;Lo;0;L;;;;;N;;;;; 112C1;KHUDAWADI LETTER CHA;Lo;0;L;;;;;N;;;;; 112C2;KHUDAWADI LETTER JA;Lo;0;L;;;;;N;;;;; 112C3;KHUDAWADI LETTER JJA;Lo;0;L;;;;;N;;;;; 112C4;KHUDAWADI LETTER JHA;Lo;0;L;;;;;N;;;;; 112C5;KHUDAWADI LETTER NYA;Lo;0;L;;;;;N;;;;; 112C6;KHUDAWADI LETTER TTA;Lo;0;L;;;;;N;;;;; 112C7;KHUDAWADI LETTER TTHA;Lo;0;L;;;;;N;;;;; 112C8;KHUDAWADI LETTER DDA;Lo;0;L;;;;;N;;;;; 112C9;KHUDAWADI LETTER DDDA;Lo;0;L;;;;;N;;;;; 112CA;KHUDAWADI LETTER RRA;Lo;0;L;;;;;N;;;;; 112CB;KHUDAWADI LETTER DDHA;Lo;0;L;;;;;N;;;;; 112CC;KHUDAWADI LETTER NNA;Lo;0;L;;;;;N;;;;; 112CD;KHUDAWADI LETTER TA;Lo;0;L;;;;;N;;;;; 112CE;KHUDAWADI LETTER THA;Lo;0;L;;;;;N;;;;; 112CF;KHUDAWADI LETTER DA;Lo;0;L;;;;;N;;;;; 112D0;KHUDAWADI LETTER DHA;Lo;0;L;;;;;N;;;;; 112D1;KHUDAWADI LETTER NA;Lo;0;L;;;;;N;;;;; 112D2;KHUDAWADI LETTER PA;Lo;0;L;;;;;N;;;;; 112D3;KHUDAWADI LETTER PHA;Lo;0;L;;;;;N;;;;; 112D4;KHUDAWADI LETTER BA;Lo;0;L;;;;;N;;;;; 112D5;KHUDAWADI LETTER BBA;Lo;0;L;;;;;N;;;;; 112D6;KHUDAWADI LETTER BHA;Lo;0;L;;;;;N;;;;; 112D7;KHUDAWADI LETTER MA;Lo;0;L;;;;;N;;;;; 112D8;KHUDAWADI LETTER YA;Lo;0;L;;;;;N;;;;; 112D9;KHUDAWADI LETTER RA;Lo;0;L;;;;;N;;;;; 112DA;KHUDAWADI LETTER LA;Lo;0;L;;;;;N;;;;; 112DB;KHUDAWADI LETTER VA;Lo;0;L;;;;;N;;;;; 112DC;KHUDAWADI LETTER SHA;Lo;0;L;;;;;N;;;;; 112DD;KHUDAWADI LETTER SA;Lo;0;L;;;;;N;;;;; 112DE;KHUDAWADI LETTER HA;Lo;0;L;;;;;N;;;;; 112DF;KHUDAWADI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 112E0;KHUDAWADI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 112E1;KHUDAWADI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 112E2;KHUDAWADI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 112E3;KHUDAWADI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 112E4;KHUDAWADI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 112E5;KHUDAWADI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 112E6;KHUDAWADI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 112E7;KHUDAWADI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 112E8;KHUDAWADI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 112E9;KHUDAWADI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 112EA;KHUDAWADI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 112F0;KHUDAWADI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 112F1;KHUDAWADI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 112F2;KHUDAWADI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 112F3;KHUDAWADI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 112F4;KHUDAWADI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 112F5;KHUDAWADI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 112F6;KHUDAWADI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 112F7;KHUDAWADI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 112F8;KHUDAWADI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 112F9;KHUDAWADI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11301;GRANTHA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11302;GRANTHA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 11303;GRANTHA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11305;GRANTHA LETTER A;Lo;0;L;;;;;N;;;;; 11306;GRANTHA LETTER AA;Lo;0;L;;;;;N;;;;; 11307;GRANTHA LETTER I;Lo;0;L;;;;;N;;;;; 11308;GRANTHA LETTER II;Lo;0;L;;;;;N;;;;; 11309;GRANTHA LETTER U;Lo;0;L;;;;;N;;;;; 1130A;GRANTHA LETTER UU;Lo;0;L;;;;;N;;;;; 1130B;GRANTHA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1130C;GRANTHA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1130F;GRANTHA LETTER EE;Lo;0;L;;;;;N;;;;; 11310;GRANTHA LETTER AI;Lo;0;L;;;;;N;;;;; 11313;GRANTHA LETTER OO;Lo;0;L;;;;;N;;;;; 11314;GRANTHA LETTER AU;Lo;0;L;;;;;N;;;;; 11315;GRANTHA LETTER KA;Lo;0;L;;;;;N;;;;; 11316;GRANTHA LETTER KHA;Lo;0;L;;;;;N;;;;; 11317;GRANTHA LETTER GA;Lo;0;L;;;;;N;;;;; 11318;GRANTHA LETTER GHA;Lo;0;L;;;;;N;;;;; 11319;GRANTHA LETTER NGA;Lo;0;L;;;;;N;;;;; 1131A;GRANTHA LETTER CA;Lo;0;L;;;;;N;;;;; 1131B;GRANTHA LETTER CHA;Lo;0;L;;;;;N;;;;; 1131C;GRANTHA LETTER JA;Lo;0;L;;;;;N;;;;; 1131D;GRANTHA LETTER JHA;Lo;0;L;;;;;N;;;;; 1131E;GRANTHA LETTER NYA;Lo;0;L;;;;;N;;;;; 1131F;GRANTHA LETTER TTA;Lo;0;L;;;;;N;;;;; 11320;GRANTHA LETTER TTHA;Lo;0;L;;;;;N;;;;; 11321;GRANTHA LETTER DDA;Lo;0;L;;;;;N;;;;; 11322;GRANTHA LETTER DDHA;Lo;0;L;;;;;N;;;;; 11323;GRANTHA LETTER NNA;Lo;0;L;;;;;N;;;;; 11324;GRANTHA LETTER TA;Lo;0;L;;;;;N;;;;; 11325;GRANTHA LETTER THA;Lo;0;L;;;;;N;;;;; 11326;GRANTHA LETTER DA;Lo;0;L;;;;;N;;;;; 11327;GRANTHA LETTER DHA;Lo;0;L;;;;;N;;;;; 11328;GRANTHA LETTER NA;Lo;0;L;;;;;N;;;;; 1132A;GRANTHA LETTER PA;Lo;0;L;;;;;N;;;;; 1132B;GRANTHA LETTER PHA;Lo;0;L;;;;;N;;;;; 1132C;GRANTHA LETTER BA;Lo;0;L;;;;;N;;;;; 1132D;GRANTHA LETTER BHA;Lo;0;L;;;;;N;;;;; 1132E;GRANTHA LETTER MA;Lo;0;L;;;;;N;;;;; 1132F;GRANTHA LETTER YA;Lo;0;L;;;;;N;;;;; 11330;GRANTHA LETTER RA;Lo;0;L;;;;;N;;;;; 11332;GRANTHA LETTER LA;Lo;0;L;;;;;N;;;;; 11333;GRANTHA LETTER LLA;Lo;0;L;;;;;N;;;;; 11335;GRANTHA LETTER VA;Lo;0;L;;;;;N;;;;; 11336;GRANTHA LETTER SHA;Lo;0;L;;;;;N;;;;; 11337;GRANTHA LETTER SSA;Lo;0;L;;;;;N;;;;; 11338;GRANTHA LETTER SA;Lo;0;L;;;;;N;;;;; 11339;GRANTHA LETTER HA;Lo;0;L;;;;;N;;;;; 1133C;GRANTHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 1133D;GRANTHA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 1133E;GRANTHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1133F;GRANTHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11340;GRANTHA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 11341;GRANTHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 11342;GRANTHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 11343;GRANTHA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 11344;GRANTHA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 11347;GRANTHA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 11348;GRANTHA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1134B;GRANTHA VOWEL SIGN OO;Mc;0;L;11347 1133E;;;;N;;;;; 1134C;GRANTHA VOWEL SIGN AU;Mc;0;L;11347 11357;;;;N;;;;; 1134D;GRANTHA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 11357;GRANTHA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 1135D;GRANTHA SIGN PLUTA;Lo;0;L;;;;;N;;;;; 1135E;GRANTHA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; 1135F;GRANTHA LETTER VEDIC DOUBLE ANUSVARA;Lo;0;L;;;;;N;;;;; 11360;GRANTHA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11361;GRANTHA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 11362;GRANTHA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; 11363;GRANTHA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; 11366;COMBINING GRANTHA DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; 11367;COMBINING GRANTHA DIGIT ONE;Mn;230;NSM;;;;;N;;;;; 11368;COMBINING GRANTHA DIGIT TWO;Mn;230;NSM;;;;;N;;;;; 11369;COMBINING GRANTHA DIGIT THREE;Mn;230;NSM;;;;;N;;;;; 1136A;COMBINING GRANTHA DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; 1136B;COMBINING GRANTHA DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; 1136C;COMBINING GRANTHA DIGIT SIX;Mn;230;NSM;;;;;N;;;;; 11370;COMBINING GRANTHA LETTER A;Mn;230;NSM;;;;;N;;;;; 11371;COMBINING GRANTHA LETTER KA;Mn;230;NSM;;;;;N;;;;; 11372;COMBINING GRANTHA LETTER NA;Mn;230;NSM;;;;;N;;;;; 11373;COMBINING GRANTHA LETTER VI;Mn;230;NSM;;;;;N;;;;; 11374;COMBINING GRANTHA LETTER PA;Mn;230;NSM;;;;;N;;;;; 11480;TIRHUTA ANJI;Lo;0;L;;;;;N;;;;; 11481;TIRHUTA LETTER A;Lo;0;L;;;;;N;;;;; 11482;TIRHUTA LETTER AA;Lo;0;L;;;;;N;;;;; 11483;TIRHUTA LETTER I;Lo;0;L;;;;;N;;;;; 11484;TIRHUTA LETTER II;Lo;0;L;;;;;N;;;;; 11485;TIRHUTA LETTER U;Lo;0;L;;;;;N;;;;; 11486;TIRHUTA LETTER UU;Lo;0;L;;;;;N;;;;; 11487;TIRHUTA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11488;TIRHUTA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11489;TIRHUTA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1148A;TIRHUTA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1148B;TIRHUTA LETTER E;Lo;0;L;;;;;N;;;;; 1148C;TIRHUTA LETTER AI;Lo;0;L;;;;;N;;;;; 1148D;TIRHUTA LETTER O;Lo;0;L;;;;;N;;;;; 1148E;TIRHUTA LETTER AU;Lo;0;L;;;;;N;;;;; 1148F;TIRHUTA LETTER KA;Lo;0;L;;;;;N;;;;; 11490;TIRHUTA LETTER KHA;Lo;0;L;;;;;N;;;;; 11491;TIRHUTA LETTER GA;Lo;0;L;;;;;N;;;;; 11492;TIRHUTA LETTER GHA;Lo;0;L;;;;;N;;;;; 11493;TIRHUTA LETTER NGA;Lo;0;L;;;;;N;;;;; 11494;TIRHUTA LETTER CA;Lo;0;L;;;;;N;;;;; 11495;TIRHUTA LETTER CHA;Lo;0;L;;;;;N;;;;; 11496;TIRHUTA LETTER JA;Lo;0;L;;;;;N;;;;; 11497;TIRHUTA LETTER JHA;Lo;0;L;;;;;N;;;;; 11498;TIRHUTA LETTER NYA;Lo;0;L;;;;;N;;;;; 11499;TIRHUTA LETTER TTA;Lo;0;L;;;;;N;;;;; 1149A;TIRHUTA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1149B;TIRHUTA LETTER DDA;Lo;0;L;;;;;N;;;;; 1149C;TIRHUTA LETTER DDHA;Lo;0;L;;;;;N;;;;; 1149D;TIRHUTA LETTER NNA;Lo;0;L;;;;;N;;;;; 1149E;TIRHUTA LETTER TA;Lo;0;L;;;;;N;;;;; 1149F;TIRHUTA LETTER THA;Lo;0;L;;;;;N;;;;; 114A0;TIRHUTA LETTER DA;Lo;0;L;;;;;N;;;;; 114A1;TIRHUTA LETTER DHA;Lo;0;L;;;;;N;;;;; 114A2;TIRHUTA LETTER NA;Lo;0;L;;;;;N;;;;; 114A3;TIRHUTA LETTER PA;Lo;0;L;;;;;N;;;;; 114A4;TIRHUTA LETTER PHA;Lo;0;L;;;;;N;;;;; 114A5;TIRHUTA LETTER BA;Lo;0;L;;;;;N;;;;; 114A6;TIRHUTA LETTER BHA;Lo;0;L;;;;;N;;;;; 114A7;TIRHUTA LETTER MA;Lo;0;L;;;;;N;;;;; 114A8;TIRHUTA LETTER YA;Lo;0;L;;;;;N;;;;; 114A9;TIRHUTA LETTER RA;Lo;0;L;;;;;N;;;;; 114AA;TIRHUTA LETTER LA;Lo;0;L;;;;;N;;;;; 114AB;TIRHUTA LETTER VA;Lo;0;L;;;;;N;;;;; 114AC;TIRHUTA LETTER SHA;Lo;0;L;;;;;N;;;;; 114AD;TIRHUTA LETTER SSA;Lo;0;L;;;;;N;;;;; 114AE;TIRHUTA LETTER SA;Lo;0;L;;;;;N;;;;; 114AF;TIRHUTA LETTER HA;Lo;0;L;;;;;N;;;;; 114B0;TIRHUTA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 114B1;TIRHUTA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 114B2;TIRHUTA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 114B3;TIRHUTA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 114B4;TIRHUTA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 114B5;TIRHUTA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 114B6;TIRHUTA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 114B7;TIRHUTA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 114B8;TIRHUTA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 114B9;TIRHUTA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 114BA;TIRHUTA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 114BB;TIRHUTA VOWEL SIGN AI;Mc;0;L;114B9 114BA;;;;N;;;;; 114BC;TIRHUTA VOWEL SIGN O;Mc;0;L;114B9 114B0;;;;N;;;;; 114BD;TIRHUTA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 114BE;TIRHUTA VOWEL SIGN AU;Mc;0;L;114B9 114BD;;;;N;;;;; 114BF;TIRHUTA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 114C0;TIRHUTA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 114C1;TIRHUTA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 114C2;TIRHUTA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 114C3;TIRHUTA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 114C4;TIRHUTA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 114C5;TIRHUTA GVANG;Lo;0;L;;;;;N;;;;; 114C6;TIRHUTA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 114C7;TIRHUTA OM;Lo;0;L;;;;;N;;;;; 114D0;TIRHUTA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 114D1;TIRHUTA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 114D2;TIRHUTA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 114D3;TIRHUTA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 114D4;TIRHUTA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 114D5;TIRHUTA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 114D6;TIRHUTA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 114D7;TIRHUTA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 114D8;TIRHUTA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 114D9;TIRHUTA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11580;SIDDHAM LETTER A;Lo;0;L;;;;;N;;;;; 11581;SIDDHAM LETTER AA;Lo;0;L;;;;;N;;;;; 11582;SIDDHAM LETTER I;Lo;0;L;;;;;N;;;;; 11583;SIDDHAM LETTER II;Lo;0;L;;;;;N;;;;; 11584;SIDDHAM LETTER U;Lo;0;L;;;;;N;;;;; 11585;SIDDHAM LETTER UU;Lo;0;L;;;;;N;;;;; 11586;SIDDHAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11587;SIDDHAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11588;SIDDHAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11589;SIDDHAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1158A;SIDDHAM LETTER E;Lo;0;L;;;;;N;;;;; 1158B;SIDDHAM LETTER AI;Lo;0;L;;;;;N;;;;; 1158C;SIDDHAM LETTER O;Lo;0;L;;;;;N;;;;; 1158D;SIDDHAM LETTER AU;Lo;0;L;;;;;N;;;;; 1158E;SIDDHAM LETTER KA;Lo;0;L;;;;;N;;;;; 1158F;SIDDHAM LETTER KHA;Lo;0;L;;;;;N;;;;; 11590;SIDDHAM LETTER GA;Lo;0;L;;;;;N;;;;; 11591;SIDDHAM LETTER GHA;Lo;0;L;;;;;N;;;;; 11592;SIDDHAM LETTER NGA;Lo;0;L;;;;;N;;;;; 11593;SIDDHAM LETTER CA;Lo;0;L;;;;;N;;;;; 11594;SIDDHAM LETTER CHA;Lo;0;L;;;;;N;;;;; 11595;SIDDHAM LETTER JA;Lo;0;L;;;;;N;;;;; 11596;SIDDHAM LETTER JHA;Lo;0;L;;;;;N;;;;; 11597;SIDDHAM LETTER NYA;Lo;0;L;;;;;N;;;;; 11598;SIDDHAM LETTER TTA;Lo;0;L;;;;;N;;;;; 11599;SIDDHAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 1159A;SIDDHAM LETTER DDA;Lo;0;L;;;;;N;;;;; 1159B;SIDDHAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 1159C;SIDDHAM LETTER NNA;Lo;0;L;;;;;N;;;;; 1159D;SIDDHAM LETTER TA;Lo;0;L;;;;;N;;;;; 1159E;SIDDHAM LETTER THA;Lo;0;L;;;;;N;;;;; 1159F;SIDDHAM LETTER DA;Lo;0;L;;;;;N;;;;; 115A0;SIDDHAM LETTER DHA;Lo;0;L;;;;;N;;;;; 115A1;SIDDHAM LETTER NA;Lo;0;L;;;;;N;;;;; 115A2;SIDDHAM LETTER PA;Lo;0;L;;;;;N;;;;; 115A3;SIDDHAM LETTER PHA;Lo;0;L;;;;;N;;;;; 115A4;SIDDHAM LETTER BA;Lo;0;L;;;;;N;;;;; 115A5;SIDDHAM LETTER BHA;Lo;0;L;;;;;N;;;;; 115A6;SIDDHAM LETTER MA;Lo;0;L;;;;;N;;;;; 115A7;SIDDHAM LETTER YA;Lo;0;L;;;;;N;;;;; 115A8;SIDDHAM LETTER RA;Lo;0;L;;;;;N;;;;; 115A9;SIDDHAM LETTER LA;Lo;0;L;;;;;N;;;;; 115AA;SIDDHAM LETTER VA;Lo;0;L;;;;;N;;;;; 115AB;SIDDHAM LETTER SHA;Lo;0;L;;;;;N;;;;; 115AC;SIDDHAM LETTER SSA;Lo;0;L;;;;;N;;;;; 115AD;SIDDHAM LETTER SA;Lo;0;L;;;;;N;;;;; 115AE;SIDDHAM LETTER HA;Lo;0;L;;;;;N;;;;; 115AF;SIDDHAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 115B0;SIDDHAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 115B1;SIDDHAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 115B2;SIDDHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 115B3;SIDDHAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 115B4;SIDDHAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 115B5;SIDDHAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 115B8;SIDDHAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 115B9;SIDDHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 115BA;SIDDHAM VOWEL SIGN O;Mc;0;L;115B8 115AF;;;;N;;;;; 115BB;SIDDHAM VOWEL SIGN AU;Mc;0;L;115B9 115AF;;;;N;;;;; 115BC;SIDDHAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 115BD;SIDDHAM SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 115BE;SIDDHAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 115BF;SIDDHAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 115C0;SIDDHAM SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 115C1;SIDDHAM SIGN SIDDHAM;Po;0;L;;;;;N;;;;; 115C2;SIDDHAM DANDA;Po;0;L;;;;;N;;;;; 115C3;SIDDHAM DOUBLE DANDA;Po;0;L;;;;;N;;;;; 115C4;SIDDHAM SEPARATOR DOT;Po;0;L;;;;;N;;;;; 115C5;SIDDHAM SEPARATOR BAR;Po;0;L;;;;;N;;;;; 115C6;SIDDHAM REPETITION MARK-1;Po;0;L;;;;;N;;;;; 115C7;SIDDHAM REPETITION MARK-2;Po;0;L;;;;;N;;;;; 115C8;SIDDHAM REPETITION MARK-3;Po;0;L;;;;;N;;;;; 115C9;SIDDHAM END OF TEXT MARK;Po;0;L;;;;;N;;;;; 11600;MODI LETTER A;Lo;0;L;;;;;N;;;;; 11601;MODI LETTER AA;Lo;0;L;;;;;N;;;;; 11602;MODI LETTER I;Lo;0;L;;;;;N;;;;; 11603;MODI LETTER II;Lo;0;L;;;;;N;;;;; 11604;MODI LETTER U;Lo;0;L;;;;;N;;;;; 11605;MODI LETTER UU;Lo;0;L;;;;;N;;;;; 11606;MODI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11607;MODI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11608;MODI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11609;MODI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1160A;MODI LETTER E;Lo;0;L;;;;;N;;;;; 1160B;MODI LETTER AI;Lo;0;L;;;;;N;;;;; 1160C;MODI LETTER O;Lo;0;L;;;;;N;;;;; 1160D;MODI LETTER AU;Lo;0;L;;;;;N;;;;; 1160E;MODI LETTER KA;Lo;0;L;;;;;N;;;;; 1160F;MODI LETTER KHA;Lo;0;L;;;;;N;;;;; 11610;MODI LETTER GA;Lo;0;L;;;;;N;;;;; 11611;MODI LETTER GHA;Lo;0;L;;;;;N;;;;; 11612;MODI LETTER NGA;Lo;0;L;;;;;N;;;;; 11613;MODI LETTER CA;Lo;0;L;;;;;N;;;;; 11614;MODI LETTER CHA;Lo;0;L;;;;;N;;;;; 11615;MODI LETTER JA;Lo;0;L;;;;;N;;;;; 11616;MODI LETTER JHA;Lo;0;L;;;;;N;;;;; 11617;MODI LETTER NYA;Lo;0;L;;;;;N;;;;; 11618;MODI LETTER TTA;Lo;0;L;;;;;N;;;;; 11619;MODI LETTER TTHA;Lo;0;L;;;;;N;;;;; 1161A;MODI LETTER DDA;Lo;0;L;;;;;N;;;;; 1161B;MODI LETTER DDHA;Lo;0;L;;;;;N;;;;; 1161C;MODI LETTER NNA;Lo;0;L;;;;;N;;;;; 1161D;MODI LETTER TA;Lo;0;L;;;;;N;;;;; 1161E;MODI LETTER THA;Lo;0;L;;;;;N;;;;; 1161F;MODI LETTER DA;Lo;0;L;;;;;N;;;;; 11620;MODI LETTER DHA;Lo;0;L;;;;;N;;;;; 11621;MODI LETTER NA;Lo;0;L;;;;;N;;;;; 11622;MODI LETTER PA;Lo;0;L;;;;;N;;;;; 11623;MODI LETTER PHA;Lo;0;L;;;;;N;;;;; 11624;MODI LETTER BA;Lo;0;L;;;;;N;;;;; 11625;MODI LETTER BHA;Lo;0;L;;;;;N;;;;; 11626;MODI LETTER MA;Lo;0;L;;;;;N;;;;; 11627;MODI LETTER YA;Lo;0;L;;;;;N;;;;; 11628;MODI LETTER RA;Lo;0;L;;;;;N;;;;; 11629;MODI LETTER LA;Lo;0;L;;;;;N;;;;; 1162A;MODI LETTER VA;Lo;0;L;;;;;N;;;;; 1162B;MODI LETTER SHA;Lo;0;L;;;;;N;;;;; 1162C;MODI LETTER SSA;Lo;0;L;;;;;N;;;;; 1162D;MODI LETTER SA;Lo;0;L;;;;;N;;;;; 1162E;MODI LETTER HA;Lo;0;L;;;;;N;;;;; 1162F;MODI LETTER LLA;Lo;0;L;;;;;N;;;;; 11630;MODI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 11631;MODI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11632;MODI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 11633;MODI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11634;MODI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 11635;MODI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 11636;MODI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 11637;MODI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 11638;MODI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 11639;MODI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1163A;MODI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1163B;MODI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1163C;MODI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 1163D;MODI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1163E;MODI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1163F;MODI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 11640;MODI SIGN ARDHACANDRA;Mn;0;NSM;;;;;N;;;;; 11641;MODI DANDA;Po;0;L;;;;;N;;;;; 11642;MODI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11643;MODI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 11644;MODI SIGN HUVA;Lo;0;L;;;;;N;;;;; 11650;MODI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11651;MODI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11652;MODI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11653;MODI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 11654;MODI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 11655;MODI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 11656;MODI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 11657;MODI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11658;MODI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11659;MODI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;; 11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;; 11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;; 11683;TAKRI LETTER II;Lo;0;L;;;;;N;;;;; 11684;TAKRI LETTER U;Lo;0;L;;;;;N;;;;; 11685;TAKRI LETTER UU;Lo;0;L;;;;;N;;;;; 11686;TAKRI LETTER E;Lo;0;L;;;;;N;;;;; 11687;TAKRI LETTER AI;Lo;0;L;;;;;N;;;;; 11688;TAKRI LETTER O;Lo;0;L;;;;;N;;;;; 11689;TAKRI LETTER AU;Lo;0;L;;;;;N;;;;; 1168A;TAKRI LETTER KA;Lo;0;L;;;;;N;;;;; 1168B;TAKRI LETTER KHA;Lo;0;L;;;;;N;;;;; 1168C;TAKRI LETTER GA;Lo;0;L;;;;;N;;;;; 1168D;TAKRI LETTER GHA;Lo;0;L;;;;;N;;;;; 1168E;TAKRI LETTER NGA;Lo;0;L;;;;;N;;;;; 1168F;TAKRI LETTER CA;Lo;0;L;;;;;N;;;;; 11690;TAKRI LETTER CHA;Lo;0;L;;;;;N;;;;; 11691;TAKRI LETTER JA;Lo;0;L;;;;;N;;;;; 11692;TAKRI LETTER JHA;Lo;0;L;;;;;N;;;;; 11693;TAKRI LETTER NYA;Lo;0;L;;;;;N;;;;; 11694;TAKRI LETTER TTA;Lo;0;L;;;;;N;;;;; 11695;TAKRI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11696;TAKRI LETTER DDA;Lo;0;L;;;;;N;;;;; 11697;TAKRI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11698;TAKRI LETTER NNA;Lo;0;L;;;;;N;;;;; 11699;TAKRI LETTER TA;Lo;0;L;;;;;N;;;;; 1169A;TAKRI LETTER THA;Lo;0;L;;;;;N;;;;; 1169B;TAKRI LETTER DA;Lo;0;L;;;;;N;;;;; 1169C;TAKRI LETTER DHA;Lo;0;L;;;;;N;;;;; 1169D;TAKRI LETTER NA;Lo;0;L;;;;;N;;;;; 1169E;TAKRI LETTER PA;Lo;0;L;;;;;N;;;;; 1169F;TAKRI LETTER PHA;Lo;0;L;;;;;N;;;;; 116A0;TAKRI LETTER BA;Lo;0;L;;;;;N;;;;; 116A1;TAKRI LETTER BHA;Lo;0;L;;;;;N;;;;; 116A2;TAKRI LETTER MA;Lo;0;L;;;;;N;;;;; 116A3;TAKRI LETTER YA;Lo;0;L;;;;;N;;;;; 116A4;TAKRI LETTER RA;Lo;0;L;;;;;N;;;;; 116A5;TAKRI LETTER LA;Lo;0;L;;;;;N;;;;; 116A6;TAKRI LETTER VA;Lo;0;L;;;;;N;;;;; 116A7;TAKRI LETTER SHA;Lo;0;L;;;;;N;;;;; 116A8;TAKRI LETTER SA;Lo;0;L;;;;;N;;;;; 116A9;TAKRI LETTER HA;Lo;0;L;;;;;N;;;;; 116AA;TAKRI LETTER RRA;Lo;0;L;;;;;N;;;;; 116AB;TAKRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 116AC;TAKRI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 116AD;TAKRI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 116AE;TAKRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 116AF;TAKRI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 116B0;TAKRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 116B1;TAKRI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 116B2;TAKRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 116B3;TAKRI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 116B4;TAKRI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 116B5;TAKRI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 116C3;TAKRI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 116C4;TAKRI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 116C5;TAKRI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 116C6;TAKRI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 118A0;WARANG CITI CAPITAL LETTER NGAA;Lu;0;L;;;;;N;;;;118C0; 118A1;WARANG CITI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;118C1; 118A2;WARANG CITI CAPITAL LETTER WI;Lu;0;L;;;;;N;;;;118C2; 118A3;WARANG CITI CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;118C3; 118A4;WARANG CITI CAPITAL LETTER YA;Lu;0;L;;;;;N;;;;118C4; 118A5;WARANG CITI CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;118C5; 118A6;WARANG CITI CAPITAL LETTER II;Lu;0;L;;;;;N;;;;118C6; 118A7;WARANG CITI CAPITAL LETTER UU;Lu;0;L;;;;;N;;;;118C7; 118A8;WARANG CITI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;118C8; 118A9;WARANG CITI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;118C9; 118AA;WARANG CITI CAPITAL LETTER ANG;Lu;0;L;;;;;N;;;;118CA; 118AB;WARANG CITI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;118CB; 118AC;WARANG CITI CAPITAL LETTER KO;Lu;0;L;;;;;N;;;;118CC; 118AD;WARANG CITI CAPITAL LETTER ENY;Lu;0;L;;;;;N;;;;118CD; 118AE;WARANG CITI CAPITAL LETTER YUJ;Lu;0;L;;;;;N;;;;118CE; 118AF;WARANG CITI CAPITAL LETTER UC;Lu;0;L;;;;;N;;;;118CF; 118B0;WARANG CITI CAPITAL LETTER ENN;Lu;0;L;;;;;N;;;;118D0; 118B1;WARANG CITI CAPITAL LETTER ODD;Lu;0;L;;;;;N;;;;118D1; 118B2;WARANG CITI CAPITAL LETTER TTE;Lu;0;L;;;;;N;;;;118D2; 118B3;WARANG CITI CAPITAL LETTER NUNG;Lu;0;L;;;;;N;;;;118D3; 118B4;WARANG CITI CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;118D4; 118B5;WARANG CITI CAPITAL LETTER AT;Lu;0;L;;;;;N;;;;118D5; 118B6;WARANG CITI CAPITAL LETTER AM;Lu;0;L;;;;;N;;;;118D6; 118B7;WARANG CITI CAPITAL LETTER BU;Lu;0;L;;;;;N;;;;118D7; 118B8;WARANG CITI CAPITAL LETTER PU;Lu;0;L;;;;;N;;;;118D8; 118B9;WARANG CITI CAPITAL LETTER HIYO;Lu;0;L;;;;;N;;;;118D9; 118BA;WARANG CITI CAPITAL LETTER HOLO;Lu;0;L;;;;;N;;;;118DA; 118BB;WARANG CITI CAPITAL LETTER HORR;Lu;0;L;;;;;N;;;;118DB; 118BC;WARANG CITI CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;118DC; 118BD;WARANG CITI CAPITAL LETTER SSUU;Lu;0;L;;;;;N;;;;118DD; 118BE;WARANG CITI CAPITAL LETTER SII;Lu;0;L;;;;;N;;;;118DE; 118BF;WARANG CITI CAPITAL LETTER VIYO;Lu;0;L;;;;;N;;;;118DF; 118C0;WARANG CITI SMALL LETTER NGAA;Ll;0;L;;;;;N;;;118A0;;118A0 118C1;WARANG CITI SMALL LETTER A;Ll;0;L;;;;;N;;;118A1;;118A1 118C2;WARANG CITI SMALL LETTER WI;Ll;0;L;;;;;N;;;118A2;;118A2 118C3;WARANG CITI SMALL LETTER YU;Ll;0;L;;;;;N;;;118A3;;118A3 118C4;WARANG CITI SMALL LETTER YA;Ll;0;L;;;;;N;;;118A4;;118A4 118C5;WARANG CITI SMALL LETTER YO;Ll;0;L;;;;;N;;;118A5;;118A5 118C6;WARANG CITI SMALL LETTER II;Ll;0;L;;;;;N;;;118A6;;118A6 118C7;WARANG CITI SMALL LETTER UU;Ll;0;L;;;;;N;;;118A7;;118A7 118C8;WARANG CITI SMALL LETTER E;Ll;0;L;;;;;N;;;118A8;;118A8 118C9;WARANG CITI SMALL LETTER O;Ll;0;L;;;;;N;;;118A9;;118A9 118CA;WARANG CITI SMALL LETTER ANG;Ll;0;L;;;;;N;;;118AA;;118AA 118CB;WARANG CITI SMALL LETTER GA;Ll;0;L;;;;;N;;;118AB;;118AB 118CC;WARANG CITI SMALL LETTER KO;Ll;0;L;;;;;N;;;118AC;;118AC 118CD;WARANG CITI SMALL LETTER ENY;Ll;0;L;;;;;N;;;118AD;;118AD 118CE;WARANG CITI SMALL LETTER YUJ;Ll;0;L;;;;;N;;;118AE;;118AE 118CF;WARANG CITI SMALL LETTER UC;Ll;0;L;;;;;N;;;118AF;;118AF 118D0;WARANG CITI SMALL LETTER ENN;Ll;0;L;;;;;N;;;118B0;;118B0 118D1;WARANG CITI SMALL LETTER ODD;Ll;0;L;;;;;N;;;118B1;;118B1 118D2;WARANG CITI SMALL LETTER TTE;Ll;0;L;;;;;N;;;118B2;;118B2 118D3;WARANG CITI SMALL LETTER NUNG;Ll;0;L;;;;;N;;;118B3;;118B3 118D4;WARANG CITI SMALL LETTER DA;Ll;0;L;;;;;N;;;118B4;;118B4 118D5;WARANG CITI SMALL LETTER AT;Ll;0;L;;;;;N;;;118B5;;118B5 118D6;WARANG CITI SMALL LETTER AM;Ll;0;L;;;;;N;;;118B6;;118B6 118D7;WARANG CITI SMALL LETTER BU;Ll;0;L;;;;;N;;;118B7;;118B7 118D8;WARANG CITI SMALL LETTER PU;Ll;0;L;;;;;N;;;118B8;;118B8 118D9;WARANG CITI SMALL LETTER HIYO;Ll;0;L;;;;;N;;;118B9;;118B9 118DA;WARANG CITI SMALL LETTER HOLO;Ll;0;L;;;;;N;;;118BA;;118BA 118DB;WARANG CITI SMALL LETTER HORR;Ll;0;L;;;;;N;;;118BB;;118BB 118DC;WARANG CITI SMALL LETTER HAR;Ll;0;L;;;;;N;;;118BC;;118BC 118DD;WARANG CITI SMALL LETTER SSUU;Ll;0;L;;;;;N;;;118BD;;118BD 118DE;WARANG CITI SMALL LETTER SII;Ll;0;L;;;;;N;;;118BE;;118BE 118DF;WARANG CITI SMALL LETTER VIYO;Ll;0;L;;;;;N;;;118BF;;118BF 118E0;WARANG CITI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 118E1;WARANG CITI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 118E2;WARANG CITI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 118E3;WARANG CITI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 118E4;WARANG CITI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 118E5;WARANG CITI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 118E6;WARANG CITI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 118E7;WARANG CITI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 118E8;WARANG CITI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 118E9;WARANG CITI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 118EA;WARANG CITI NUMBER TEN;No;0;L;;;;10;N;;;;; 118EB;WARANG CITI NUMBER TWENTY;No;0;L;;;;20;N;;;;; 118EC;WARANG CITI NUMBER THIRTY;No;0;L;;;;30;N;;;;; 118ED;WARANG CITI NUMBER FORTY;No;0;L;;;;40;N;;;;; 118EE;WARANG CITI NUMBER FIFTY;No;0;L;;;;50;N;;;;; 118EF;WARANG CITI NUMBER SIXTY;No;0;L;;;;60;N;;;;; 118F0;WARANG CITI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; 118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; 11AC3;PAU CIN HAU LETTER MA;Lo;0;L;;;;;N;;;;; 11AC4;PAU CIN HAU LETTER DA;Lo;0;L;;;;;N;;;;; 11AC5;PAU CIN HAU LETTER ZA;Lo;0;L;;;;;N;;;;; 11AC6;PAU CIN HAU LETTER VA;Lo;0;L;;;;;N;;;;; 11AC7;PAU CIN HAU LETTER NGA;Lo;0;L;;;;;N;;;;; 11AC8;PAU CIN HAU LETTER HA;Lo;0;L;;;;;N;;;;; 11AC9;PAU CIN HAU LETTER GA;Lo;0;L;;;;;N;;;;; 11ACA;PAU CIN HAU LETTER KHA;Lo;0;L;;;;;N;;;;; 11ACB;PAU CIN HAU LETTER SA;Lo;0;L;;;;;N;;;;; 11ACC;PAU CIN HAU LETTER BA;Lo;0;L;;;;;N;;;;; 11ACD;PAU CIN HAU LETTER CA;Lo;0;L;;;;;N;;;;; 11ACE;PAU CIN HAU LETTER TA;Lo;0;L;;;;;N;;;;; 11ACF;PAU CIN HAU LETTER THA;Lo;0;L;;;;;N;;;;; 11AD0;PAU CIN HAU LETTER NA;Lo;0;L;;;;;N;;;;; 11AD1;PAU CIN HAU LETTER PHA;Lo;0;L;;;;;N;;;;; 11AD2;PAU CIN HAU LETTER RA;Lo;0;L;;;;;N;;;;; 11AD3;PAU CIN HAU LETTER FA;Lo;0;L;;;;;N;;;;; 11AD4;PAU CIN HAU LETTER CHA;Lo;0;L;;;;;N;;;;; 11AD5;PAU CIN HAU LETTER A;Lo;0;L;;;;;N;;;;; 11AD6;PAU CIN HAU LETTER E;Lo;0;L;;;;;N;;;;; 11AD7;PAU CIN HAU LETTER I;Lo;0;L;;;;;N;;;;; 11AD8;PAU CIN HAU LETTER O;Lo;0;L;;;;;N;;;;; 11AD9;PAU CIN HAU LETTER U;Lo;0;L;;;;;N;;;;; 11ADA;PAU CIN HAU LETTER UA;Lo;0;L;;;;;N;;;;; 11ADB;PAU CIN HAU LETTER IA;Lo;0;L;;;;;N;;;;; 11ADC;PAU CIN HAU LETTER FINAL P;Lo;0;L;;;;;N;;;;; 11ADD;PAU CIN HAU LETTER FINAL K;Lo;0;L;;;;;N;;;;; 11ADE;PAU CIN HAU LETTER FINAL T;Lo;0;L;;;;;N;;;;; 11ADF;PAU CIN HAU LETTER FINAL M;Lo;0;L;;;;;N;;;;; 11AE0;PAU CIN HAU LETTER FINAL N;Lo;0;L;;;;;N;;;;; 11AE1;PAU CIN HAU LETTER FINAL L;Lo;0;L;;;;;N;;;;; 11AE2;PAU CIN HAU LETTER FINAL W;Lo;0;L;;;;;N;;;;; 11AE3;PAU CIN HAU LETTER FINAL NG;Lo;0;L;;;;;N;;;;; 11AE4;PAU CIN HAU LETTER FINAL Y;Lo;0;L;;;;;N;;;;; 11AE5;PAU CIN HAU RISING TONE LONG;Lo;0;L;;;;;N;;;;; 11AE6;PAU CIN HAU RISING TONE;Lo;0;L;;;;;N;;;;; 11AE7;PAU CIN HAU SANDHI GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 11AE8;PAU CIN HAU RISING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AE9;PAU CIN HAU RISING TONE FINAL;Lo;0;L;;;;;N;;;;; 11AEA;PAU CIN HAU SANDHI GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; 11AEB;PAU CIN HAU SANDHI TONE LONG;Lo;0;L;;;;;N;;;;; 11AEC;PAU CIN HAU SANDHI TONE;Lo;0;L;;;;;N;;;;; 11AED;PAU CIN HAU SANDHI TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AEE;PAU CIN HAU SANDHI TONE FINAL;Lo;0;L;;;;;N;;;;; 11AEF;PAU CIN HAU MID-LEVEL TONE;Lo;0;L;;;;;N;;;;; 11AF0;PAU CIN HAU GLOTTAL STOP VARIANT;Lo;0;L;;;;;N;;;;; 11AF1;PAU CIN HAU MID-LEVEL TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AF2;PAU CIN HAU MID-LEVEL TONE FINAL;Lo;0;L;;;;;N;;;;; 11AF3;PAU CIN HAU LOW-FALLING TONE LONG;Lo;0;L;;;;;N;;;;; 11AF4;PAU CIN HAU LOW-FALLING TONE;Lo;0;L;;;;;N;;;;; 11AF5;PAU CIN HAU GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 11AF6;PAU CIN HAU LOW-FALLING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AF7;PAU CIN HAU LOW-FALLING TONE FINAL;Lo;0;L;;;;;N;;;;; 11AF8;PAU CIN HAU GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; 12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;; 12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;; 12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;; 12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;; 12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;; 12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;; 1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;; 1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;; 1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;; 1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;; 12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;; 12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;; 12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;; 12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;; 12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;; 12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;; 1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;; 1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;; 1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;; 1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;; 12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;; 12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;; 12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;; 12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;; 12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;; 12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;; 12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;; 12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;; 12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;; 12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;; 1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;; 1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;; 1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;; 1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;; 1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;; 1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;; 12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;; 12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;; 12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;; 12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;; 12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;; 12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;; 12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;; 12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;; 12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;; 12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;; 1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;; 1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;; 1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;; 12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;; 12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;; 12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;; 12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;; 12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;; 12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;; 12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;; 12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;; 12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;; 12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;; 1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;; 1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;; 1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;; 1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;; 1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;; 12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;; 12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;; 12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;; 12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;; 12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;; 12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;; 12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;; 12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;; 12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;; 12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;; 1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;; 1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;; 1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;; 1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;; 1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;; 12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;; 12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;; 12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;; 12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;; 12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;; 12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;; 12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;; 12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;; 12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;; 12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; 1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;; 1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;; 1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;; 1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;; 1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;; 12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;; 12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;; 12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;; 12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;; 12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;; 12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;; 12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;; 12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;; 12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;; 1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;; 1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;; 1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;; 1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;; 1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;; 1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;; 12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;; 12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;; 12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;; 12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;; 12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;; 12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;; 12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;; 12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;; 12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;; 1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;; 1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;; 1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;; 1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;; 1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;; 12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;; 12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;; 12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;; 12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;; 12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;; 12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;; 12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;; 12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;; 12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;; 12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;; 1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;; 1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;; 1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;; 1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;; 1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;; 120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;; 120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;; 120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;; 120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;; 120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;; 120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;; 120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;; 120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;; 120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;; 120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;; 120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;; 120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;; 120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;; 120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;; 120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;; 120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;; 120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;; 120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;; 120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;; 120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;; 120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;; 120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;; 120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;; 120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;; 120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;; 120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;; 120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;; 120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;; 120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;; 120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;; 120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;; 120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;; 120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;; 120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;; 120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;; 120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;; 120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;; 120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;; 120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;; 120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;; 120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;; 120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;; 120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;; 120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;; 120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;; 120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;; 120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;; 120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;; 120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;; 120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;; 120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;; 120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;; 120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;; 120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;; 120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;; 120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;; 120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;; 120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;; 120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;; 120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;; 120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;; 120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;; 120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;; 120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;; 120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;; 120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;; 120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;; 120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;; 120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;; 120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;; 120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;; 120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;; 120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;; 120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;; 12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;; 12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;; 12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;; 12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;; 12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;; 12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;; 12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;; 12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;; 12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;; 12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;; 1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;; 1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;; 1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;; 1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;; 12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;; 12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;; 12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;; 12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;; 12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;; 12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;; 12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;; 12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;; 1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;; 1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;; 1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;; 1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;; 12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;; 12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;; 12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;; 12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;; 12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;; 12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;; 12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;; 12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;; 12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;; 12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;; 1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;; 1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;; 1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;; 1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;; 1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;; 1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;; 12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;; 12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;; 12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;; 12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;; 12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;; 12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;; 12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;; 12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;; 1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;; 1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;; 1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;; 1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;; 1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;; 12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;; 12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;; 12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;; 12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;; 12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;; 12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;; 12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;; 12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;; 12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;; 12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;; 1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;; 1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;; 1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;; 1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;; 1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;; 12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;; 12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;; 12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;; 12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;; 12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;; 12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;; 12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;; 12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;; 12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;; 12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;; 1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;; 1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;; 1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;; 1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;; 1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;; 1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;; 12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;; 12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;; 12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;; 12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;; 12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;; 12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;; 12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;; 12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;; 12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;; 1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;; 1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;; 1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;; 1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;; 1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;; 12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;; 12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;; 12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;; 12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;; 12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;; 12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;; 12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;; 12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;; 12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;; 12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;; 1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;; 1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;; 1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;; 1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;; 1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;; 1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;; 12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;; 12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;; 12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;; 12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;; 12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;; 12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;; 12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;; 12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;; 12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;; 12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;; 1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;; 1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;; 1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;; 1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;; 1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;; 12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;; 12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;; 12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;; 12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;; 12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;; 12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;; 12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;; 12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;; 12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;; 1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;; 1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;; 1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;; 1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;; 121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;; 121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;; 121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;; 121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;; 121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;; 121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;; 121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;; 121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;; 121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;; 121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;; 121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;; 121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;; 121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;; 121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;; 121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;; 121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;; 121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;; 121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;; 121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;; 121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;; 121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;; 121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;; 121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;; 121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;; 121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;; 121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;; 121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;; 121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;; 121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;; 121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;; 121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;; 121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;; 121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;; 121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;; 121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;; 121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;; 121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;; 121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;; 121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;; 121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;; 121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;; 121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;; 121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;; 121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;; 121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;; 121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;; 121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;; 121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;; 121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;; 121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;; 121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;; 121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;; 121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;; 121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;; 121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;; 121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;; 121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;; 121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;; 121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;; 121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;; 121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;; 121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;; 121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;; 121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;; 121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;; 121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;; 121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;; 121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;; 121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;; 121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;; 121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;; 121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;; 121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;; 121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;; 121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;; 121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;; 121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;; 121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;; 121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;; 121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;; 121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;; 121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;; 12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;; 12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;; 12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;; 12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;; 12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;; 12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;; 12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;; 1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;; 1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;; 1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;; 1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;; 12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;; 12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;; 12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;; 12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;; 12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;; 12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;; 12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;; 12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;; 12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;; 12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;; 1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;; 1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;; 1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;; 1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;; 1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;; 1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;; 12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;; 12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;; 12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;; 12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;; 12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;; 12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;; 12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;; 12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;; 12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;; 1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;; 1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;; 1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;; 1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;; 1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;; 1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;; 12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;; 12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;; 12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;; 12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;; 12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;; 12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;; 12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;; 12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;; 12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;; 1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;; 1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;; 1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;; 1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;; 1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;; 1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;; 12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;; 12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;; 12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;; 12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;; 12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;; 12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;; 12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;; 12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;; 12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;; 12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;; 1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;; 1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;; 1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;; 1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;; 1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;; 1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;; 12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;; 12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;; 12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;; 12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;; 1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;; 1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;; 12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;; 12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;; 12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;; 12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;; 12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;; 12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;; 12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;; 12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;; 1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;; 1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;; 1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;; 1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;; 12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;; 12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;; 12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;; 12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;; 12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;; 12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;; 1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;; 1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;; 1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;; 1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;; 1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;; 1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;; 12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;; 12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;; 12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;; 12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;; 12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;; 12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;; 12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;; 12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;; 12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;; 12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;; 1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;; 1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;; 1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;; 1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;; 1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;; 1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;; 12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;; 12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;; 12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;; 12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;; 12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;; 12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;; 12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;; 12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;; 12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;; 12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;; 1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;; 1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;; 1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;; 1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;; 1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;; 1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;; 122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;; 122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;; 122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;; 122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;; 122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;; 122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;; 122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;; 122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;; 122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;; 122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;; 122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;; 122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;; 122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;; 122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;; 122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;; 122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;; 122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;; 122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;; 122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;; 122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;; 122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;; 122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;; 122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;; 122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;; 122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;; 122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;; 122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;; 122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;; 122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;; 122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;; 122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;; 122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;; 122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;; 122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;; 122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;; 122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;; 122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;; 122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;; 122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;; 122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;; 122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;; 122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;; 122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;; 122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;; 122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;; 122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;; 122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;; 122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;; 122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;; 122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;; 122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;; 122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;; 122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;; 122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;; 122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;; 122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;; 122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;; 122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;; 122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;; 122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;; 122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;; 122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;; 122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;; 122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;; 122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;; 122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;; 122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;; 122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;; 122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;; 122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;; 122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;; 122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;; 122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;; 122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;; 122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;; 122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;; 122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;; 122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;; 122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;; 122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;; 122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;; 122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;; 122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;; 122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;; 122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;; 122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;; 122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;; 122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;; 122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;; 122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;; 122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;; 122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;; 12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;; 12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;; 12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;; 12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;; 12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;; 12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;; 12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;; 12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;; 12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;; 1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;; 1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;; 1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;; 1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;; 1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;; 1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;; 12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;; 12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;; 12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;; 12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;; 12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;; 12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;; 12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;; 12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;; 12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;; 1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;; 1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; 1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;; 1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;; 1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;; 12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;; 12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;; 12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;; 12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;; 12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;; 12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;; 12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;; 12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;; 12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;; 1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;; 1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;; 1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;; 1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;; 12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;; 12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;; 12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;; 12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;; 12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;; 12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;; 12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;; 12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;; 12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;; 1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;; 1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;; 1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;; 1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;; 12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;; 12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;; 12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;; 12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;; 12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;; 12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;; 12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;; 12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;; 12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;; 12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;; 1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;; 1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;; 1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;; 1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;; 1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;; 1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;; 12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;; 12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;; 12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;; 12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;; 12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;; 12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;; 12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;; 12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;; 12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;; 1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;; 1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;; 1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;; 1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;; 1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;; 12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;; 12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;; 12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;; 12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;; 12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;; 12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;; 12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;; 12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;; 12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;; 12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;; 1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;; 1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;; 1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;; 1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;; 1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;; 1236F;CUNEIFORM SIGN KAP ELAMITE;Lo;0;L;;;;;N;;;;; 12370;CUNEIFORM SIGN AB TIMES NUN;Lo;0;L;;;;;N;;;;; 12371;CUNEIFORM SIGN AB2 TIMES A;Lo;0;L;;;;;N;;;;; 12372;CUNEIFORM SIGN AMAR TIMES KUG;Lo;0;L;;;;;N;;;;; 12373;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS MASH;Lo;0;L;;;;;N;;;;; 12374;CUNEIFORM SIGN DAG3;Lo;0;L;;;;;N;;;;; 12375;CUNEIFORM SIGN DISH PLUS SHU;Lo;0;L;;;;;N;;;;; 12376;CUNEIFORM SIGN DUB TIMES SHE;Lo;0;L;;;;;N;;;;; 12377;CUNEIFORM SIGN EZEN TIMES GUD;Lo;0;L;;;;;N;;;;; 12378;CUNEIFORM SIGN EZEN TIMES SHE;Lo;0;L;;;;;N;;;;; 12379;CUNEIFORM SIGN GA2 TIMES AN PLUS KAK PLUS A;Lo;0;L;;;;;N;;;;; 1237A;CUNEIFORM SIGN GA2 TIMES ASH2;Lo;0;L;;;;;N;;;;; 1237B;CUNEIFORM SIGN GE22;Lo;0;L;;;;;N;;;;; 1237C;CUNEIFORM SIGN GIG;Lo;0;L;;;;;N;;;;; 1237D;CUNEIFORM SIGN HUSH;Lo;0;L;;;;;N;;;;; 1237E;CUNEIFORM SIGN KA TIMES ANSHE;Lo;0;L;;;;;N;;;;; 1237F;CUNEIFORM SIGN KA TIMES ASH3;Lo;0;L;;;;;N;;;;; 12380;CUNEIFORM SIGN KA TIMES GISH;Lo;0;L;;;;;N;;;;; 12381;CUNEIFORM SIGN KA TIMES GUD;Lo;0;L;;;;;N;;;;; 12382;CUNEIFORM SIGN KA TIMES HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 12383;CUNEIFORM SIGN KA TIMES LUM;Lo;0;L;;;;;N;;;;; 12384;CUNEIFORM SIGN KA TIMES PA;Lo;0;L;;;;;N;;;;; 12385;CUNEIFORM SIGN KA TIMES SHUL;Lo;0;L;;;;;N;;;;; 12386;CUNEIFORM SIGN KA TIMES TU;Lo;0;L;;;;;N;;;;; 12387;CUNEIFORM SIGN KA TIMES UR2;Lo;0;L;;;;;N;;;;; 12388;CUNEIFORM SIGN LAGAB TIMES GI;Lo;0;L;;;;;N;;;;; 12389;CUNEIFORM SIGN LU2 SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; 1238A;CUNEIFORM SIGN LU2 TIMES ESH2 PLUS LAL;Lo;0;L;;;;;N;;;;; 1238B;CUNEIFORM SIGN LU2 TIMES SHU;Lo;0;L;;;;;N;;;;; 1238C;CUNEIFORM SIGN MESH;Lo;0;L;;;;;N;;;;; 1238D;CUNEIFORM SIGN MUSH3 TIMES ZA;Lo;0;L;;;;;N;;;;; 1238E;CUNEIFORM SIGN NA4;Lo;0;L;;;;;N;;;;; 1238F;CUNEIFORM SIGN NIN;Lo;0;L;;;;;N;;;;; 12390;CUNEIFORM SIGN NIN9;Lo;0;L;;;;;N;;;;; 12391;CUNEIFORM SIGN NINDA2 TIMES BAL;Lo;0;L;;;;;N;;;;; 12392;CUNEIFORM SIGN NINDA2 TIMES GI;Lo;0;L;;;;;N;;;;; 12393;CUNEIFORM SIGN NU11 ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; 12394;CUNEIFORM SIGN PESH2 ASTERISK;Lo;0;L;;;;;N;;;;; 12395;CUNEIFORM SIGN PIR2;Lo;0;L;;;;;N;;;;; 12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;; 12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;; 12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;; 12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;; 12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;; 12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;; 12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;; 12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;; 12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;; 12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;; 12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;; 12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;; 1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;; 1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;; 1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;; 1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;; 1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;; 1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;; 12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;; 12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;; 12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;; 12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;; 12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;; 12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;; 12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;; 12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;; 12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;; 12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;; 1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;; 1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;; 1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;; 1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;; 1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;; 1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;; 12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;; 12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;; 12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;; 12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;; 12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;; 12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;; 12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;; 12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;; 12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;; 1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;; 1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;; 1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;; 1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;; 1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;; 1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;; 12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;; 12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;216000;N;;;;; 12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;432000;N;;;;; 12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;; 12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;; 12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;; 12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;; 12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;; 1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;; 1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;; 1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;; 1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;; 1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;; 1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;; 12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;; 12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;; 12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;; 12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;; 12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;; 12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;; 12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;; 12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;; 12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;; 12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;; 1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;; 1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;; 1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;; 1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;; 1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;; 1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;; 12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;; 12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;; 12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;; 12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;; 12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;; 12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;; 12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;2;N;;;;; 12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;3;N;;;;; 12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;; 12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;; 1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;; 1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;; 1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;; 1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;; 1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;; 1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;; 12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;; 12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;; 12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;; 12463;CUNEIFORM NUMERIC SIGN ONE QUARTER GUR;Nl;0;L;;;;1/4;N;;;;; 12464;CUNEIFORM NUMERIC SIGN ONE HALF GUR;Nl;0;L;;;;1/2;N;;;;; 12465;CUNEIFORM NUMERIC SIGN ELAMITE ONE THIRD;Nl;0;L;;;;1/3;N;;;;; 12466;CUNEIFORM NUMERIC SIGN ELAMITE TWO THIRDS;Nl;0;L;;;;2/3;N;;;;; 12467;CUNEIFORM NUMERIC SIGN ELAMITE FORTY;Nl;0;L;;;;40;N;;;;; 12468;CUNEIFORM NUMERIC SIGN ELAMITE FIFTY;Nl;0;L;;;;50;N;;;;; 12469;CUNEIFORM NUMERIC SIGN FOUR U VARIANT FORM;Nl;0;L;;;;4;N;;;;; 1246A;CUNEIFORM NUMERIC SIGN FIVE U VARIANT FORM;Nl;0;L;;;;5;N;;;;; 1246B;CUNEIFORM NUMERIC SIGN SIX U VARIANT FORM;Nl;0;L;;;;6;N;;;;; 1246C;CUNEIFORM NUMERIC SIGN SEVEN U VARIANT FORM;Nl;0;L;;;;7;N;;;;; 1246D;CUNEIFORM NUMERIC SIGN EIGHT U VARIANT FORM;Nl;0;L;;;;8;N;;;;; 1246E;CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM;Nl;0;L;;;;9;N;;;;; 12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;; 12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;; 12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;; 12474;CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON;Po;0;L;;;;;N;;;;; 13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; 13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; 13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; 13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; 13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; 13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;; 13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; 13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;; 13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;; 13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; 1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; 1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; 1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; 1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; 1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; 1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; 13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; 13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;; 13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; 13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; 13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; 13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;; 13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; 13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; 13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; 13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; 1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; 1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; 1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; 1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; 1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; 1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; 13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; 13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; 13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; 13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; 13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; 13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;; 13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; 13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; 13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; 13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; 1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; 1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; 1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; 1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; 1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;; 1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; 13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; 13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;; 13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; 13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;; 13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; 13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; 13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; 13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; 13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; 13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; 1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; 1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; 1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; 1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; 1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; 1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; 13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; 13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; 13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; 13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; 13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; 13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; 13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; 13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; 13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; 13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; 1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; 1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; 1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; 1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; 1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; 1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; 13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;; 13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;; 13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;; 13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;; 13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;; 13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;; 13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;; 13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;; 13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;; 13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;; 1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;; 1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;; 1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;; 1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;; 1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;; 1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;; 13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;; 13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;; 13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;; 13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;; 13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;; 13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;; 13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;; 13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;; 13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;; 13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;; 1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;; 1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;; 1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;; 1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;; 1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;; 1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;; 13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;; 13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;; 13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;; 13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;; 13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;; 13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;; 13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;; 13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;; 13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;; 13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;; 1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;; 1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;; 1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;; 1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;; 1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;; 1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;; 13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;; 13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;; 13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;; 13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;; 13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;; 13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;; 13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;; 13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;; 13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;; 13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;; 1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;; 1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;; 1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;; 1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;; 1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;; 1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;; 13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;; 13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;; 13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;; 13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;; 13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;; 13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;; 13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;; 13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;; 13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;; 13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;; 1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;; 1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;; 1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;; 1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;; 1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;; 1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;; 130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;; 130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;; 130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;; 130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;; 130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;; 130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;; 130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;; 130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;; 130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;; 130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;; 130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;; 130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;; 130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;; 130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;; 130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;; 130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;; 130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;; 130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;; 130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;; 130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;; 130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;; 130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;; 130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;; 130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;; 130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;; 130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;; 130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;; 130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;; 130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;; 130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;; 130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;; 130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;; 130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;; 130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;; 130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;; 130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;; 130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;; 130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;; 130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;; 130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;; 130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;; 130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;; 130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;; 130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;; 130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;; 130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;; 130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;; 130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;; 130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;; 130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;; 130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;; 130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;; 130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;; 130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;; 130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;; 130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;; 130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;; 130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;; 130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;; 130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;; 130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;; 130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;; 130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;; 130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;; 130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;; 130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;; 130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;; 130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;; 130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;; 130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;; 130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;; 130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;; 130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;; 130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;; 130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;; 130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;; 130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;; 130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;; 130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;; 130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;; 130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;; 130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;; 130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;; 130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;; 130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;; 130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;; 130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;; 130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;; 130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;; 130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;; 130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;; 130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;; 130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;; 130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;; 130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;; 130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;; 13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;; 13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;; 13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;; 13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;; 13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;; 13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;; 13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;; 13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;; 13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;; 13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;; 1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;; 1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;; 1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;; 1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;; 1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;; 1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;; 13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;; 13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;; 13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;; 13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;; 13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;; 13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;; 13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;; 13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;; 13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;; 13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;; 1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;; 1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;; 1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;; 1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;; 1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;; 1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;; 13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;; 13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;; 13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;; 13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;; 13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;; 13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;; 13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;; 13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;; 13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;; 13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;; 1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;; 1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;; 1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;; 1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;; 1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;; 1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;; 13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;; 13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;; 13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;; 13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;; 13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;; 13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;; 13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;; 13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;; 13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;; 13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;; 1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;; 1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;; 1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;; 1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;; 1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;; 1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;; 13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;; 13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;; 13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;; 13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;; 13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;; 13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;; 13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;; 13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;; 13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;; 13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;; 1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;; 1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;; 1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;; 1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;; 1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;; 1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;; 13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;; 13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;; 13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;; 13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;; 13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;; 13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;; 13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;; 13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;; 13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;; 13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;; 1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;; 1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;; 1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;; 1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;; 1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;; 1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;; 13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;; 13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;; 13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;; 13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;; 13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;; 13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;; 13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;; 13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;; 13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;; 13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;; 1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;; 1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;; 1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;; 1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;; 1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;; 1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;; 13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;; 13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;; 13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;; 13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;; 13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;; 13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;; 13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;; 13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;; 13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;; 13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;; 1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;; 1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;; 1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;; 1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;; 1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;; 1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;; 13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;; 13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;; 13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;; 13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;; 13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;; 13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;; 13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;; 13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;; 13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;; 13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;; 1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;; 1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;; 1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;; 1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;; 1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;; 1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;; 13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;; 13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;; 13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;; 13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;; 13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;; 13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;; 13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;; 13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;; 13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;; 13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;; 1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;; 1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;; 1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;; 1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;; 1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;; 1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;; 131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;; 131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;; 131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;; 131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;; 131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;; 131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;; 131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;; 131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;; 131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;; 131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;; 131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;; 131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;; 131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;; 131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;; 131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;; 131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;; 131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;; 131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;; 131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;; 131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;; 131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;; 131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;; 131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;; 131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;; 131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;; 131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;; 131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;; 131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;; 131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;; 131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;; 131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;; 131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;; 131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;; 131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;; 131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;; 131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;; 131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;; 131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;; 131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;; 131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;; 131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;; 131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;; 131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;; 131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;; 131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;; 131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;; 131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;; 131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;; 131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;; 131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;; 131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;; 131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;; 131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;; 131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;; 131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;; 131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;; 131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;; 131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;; 131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;; 131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;; 131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;; 131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;; 131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;; 131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;; 131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;; 131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;; 131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;; 131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;; 131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;; 131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;; 131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;; 131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;; 131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;; 131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;; 131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;; 131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;; 131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;; 131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;; 131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;; 131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;; 131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;; 131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;; 131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;; 131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;; 131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;; 131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;; 131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;; 131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;; 131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;; 131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;; 131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;; 131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;; 131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;; 131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;; 131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;; 131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;; 13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;; 13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;; 13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;; 13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;; 13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;; 13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;; 13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;; 13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;; 13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;; 13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;; 1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;; 1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;; 1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;; 1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;; 1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;; 1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;; 13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;; 13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;; 13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;; 13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;; 13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;; 13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;; 13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;; 13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;; 13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;; 13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;; 1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;; 1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;; 1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;; 1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;; 1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;; 1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;; 13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;; 13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;; 13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;; 13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;; 13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;; 13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;; 13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;; 13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;; 13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;; 13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;; 1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;; 1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;; 1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;; 1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;; 1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;; 1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;; 13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;; 13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;; 13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;; 13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;; 13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;; 13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;; 13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;; 13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;; 13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;; 13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;; 1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;; 1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;; 1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;; 1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;; 1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;; 1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;; 13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;; 13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;; 13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;; 13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;; 13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;; 13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;; 13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;; 13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;; 13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;; 13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;; 1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;; 1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;; 1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;; 1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;; 1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;; 1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;; 13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;; 13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;; 13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;; 13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;; 13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;; 13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;; 13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;; 13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;; 13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;; 13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;; 1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;; 1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;; 1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;; 1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;; 1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;; 1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;; 13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;; 13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;; 13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;; 13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;; 13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;; 13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;; 13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;; 13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;; 13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;; 13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;; 1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;; 1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;; 1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;; 1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;; 1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;; 1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;; 13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;; 13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;; 13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;; 13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;; 13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;; 13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;; 13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;; 13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;; 13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;; 13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;; 1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;; 1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;; 1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;; 1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;; 1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;; 1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;; 13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;; 13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;; 13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;; 13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;; 13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;; 13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;; 13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;; 13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;; 13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;; 13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;; 1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;; 1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;; 1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;; 1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;; 1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;; 1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;; 13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;; 13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;; 13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;; 13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;; 13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;; 13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;; 13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;; 13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;; 13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;; 13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;; 1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;; 1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;; 1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;; 1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;; 1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;; 1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;; 132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;; 132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;; 132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;; 132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;; 132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;; 132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;; 132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;; 132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;; 132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;; 132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;; 132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;; 132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;; 132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;; 132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;; 132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;; 132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;; 132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;; 132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;; 132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;; 132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;; 132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;; 132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;; 132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;; 132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;; 132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;; 132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;; 132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;; 132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;; 132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;; 132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;; 132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;; 132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;; 132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;; 132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;; 132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;; 132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;; 132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;; 132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;; 132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;; 132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;; 132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;; 132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;; 132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;; 132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;; 132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;; 132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;; 132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;; 132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;; 132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;; 132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;; 132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;; 132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;; 132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;; 132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;; 132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;; 132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;; 132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;; 132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;; 132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;; 132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;; 132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;; 132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;; 132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;; 132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;; 132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;; 132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;; 132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;; 132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;; 132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;; 132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;; 132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;; 132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;; 132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;; 132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;; 132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;; 132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;; 132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;; 132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;; 132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;; 132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;; 132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;; 132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;; 132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;; 132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;; 132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;; 132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;; 132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;; 132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;; 132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;; 132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;; 132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;; 132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;; 132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;; 132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;; 132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;; 132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;; 13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;; 13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;; 13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;; 13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;; 13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;; 13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;; 13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;; 13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;; 13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;; 13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;; 1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;; 1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;; 1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;; 1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;; 1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;; 1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;; 13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;; 13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;; 13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;; 13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;; 13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;; 13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;; 13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;; 13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;; 13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;; 13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;; 1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;; 1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;; 1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;; 1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;; 1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;; 1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;; 13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;; 13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;; 13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;; 13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;; 13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;; 13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;; 13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;; 13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;; 13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;; 13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;; 1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;; 1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;; 1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;; 1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;; 1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;; 1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;; 13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;; 13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;; 13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;; 13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;; 13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;; 13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;; 13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;; 13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;; 13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;; 13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;; 1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;; 1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;; 1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;; 1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;; 1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;; 1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;; 13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;; 13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;; 13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;; 13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;; 13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;; 13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;; 13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;; 13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;; 13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;; 13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;; 1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;; 1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;; 1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;; 1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;; 1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;; 1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;; 13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;; 13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;; 13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;; 13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;; 13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;; 13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;; 13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;; 13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;; 13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;; 13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;; 1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;; 1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;; 1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;; 1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;; 1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;; 1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;; 13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;; 13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;; 13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;; 13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;; 13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;; 13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;; 13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;; 13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;; 13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;; 13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;; 1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;; 1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;; 1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;; 1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;; 1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;; 1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;; 13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;; 13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;; 13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;; 13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;; 13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;; 13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;; 13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;; 13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;; 13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;; 13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;; 1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;; 1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;; 1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;; 1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;; 1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;; 1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;; 13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;; 13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;; 13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;; 13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;; 13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;; 13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;; 13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;; 13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;; 13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;; 13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;; 1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;; 1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;; 1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;; 1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;; 1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;; 1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;; 13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;; 13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;; 13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;; 13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;; 13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;; 13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;; 13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;; 13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;; 13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;; 13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;; 1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;; 1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;; 1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;; 1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;; 1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;; 1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;; 133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;; 133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;; 133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;; 133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;; 133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;; 133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;; 133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;; 133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;; 133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;; 133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;; 133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;; 133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;; 133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;; 133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;; 133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;; 133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;; 133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;; 133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;; 133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;; 133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;; 133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;; 133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;; 133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;; 133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;; 133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;; 133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;; 133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;; 133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;; 133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;; 133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;; 133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;; 133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;; 133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;; 133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;; 133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;; 133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;; 133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;; 133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;; 133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;; 133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;; 133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;; 133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;; 133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;; 133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;; 133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;; 133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;; 133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;; 133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;; 133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;; 133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;; 133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;; 133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;; 133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;; 133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;; 133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;; 133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;; 133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;; 133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;; 133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;; 133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;; 133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;; 133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;; 133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;; 133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;; 133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;; 133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;; 133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;; 133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;; 133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;; 133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;; 133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;; 133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;; 133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;; 133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;; 133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;; 133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;; 133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;; 133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;; 133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;; 133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;; 133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;; 133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;; 133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;; 133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;; 133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;; 133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;; 133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;; 133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;; 133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;; 133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;; 133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;; 133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;; 133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;; 133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;; 133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;; 133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;; 13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;; 13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;; 13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;; 13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;; 13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;; 13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;; 13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;; 13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;; 13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;; 13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;; 1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;; 1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;; 1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;; 1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;; 1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;; 1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;; 13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;; 13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;; 13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;; 13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;; 13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;; 13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;; 13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;; 13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;; 13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;; 13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;; 1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;; 1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;; 1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;; 1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;; 1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;; 1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;; 13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;; 13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;; 13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;; 13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;; 13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;; 13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;; 13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;; 13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;; 13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;; 13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;; 1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;; 1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;; 1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; 1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; 1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; 16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;; 16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;; 16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; 16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;; 16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;; 16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;; 16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;; 16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;; 16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;; 16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; 1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;; 1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;; 1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;; 1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;; 1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;; 1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;; 16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;; 16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;; 16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;; 16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;; 16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;; 16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;; 16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;; 16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;; 16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;; 16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;; 1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;; 1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;; 1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;; 1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;; 1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;; 1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;; 16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;; 16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;; 16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;; 16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;; 16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;; 16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;; 16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;; 16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;; 16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;; 16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;; 1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;; 1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;; 1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;; 1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;; 1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;; 1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;; 16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;; 16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;; 16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;; 16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;; 16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;; 16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;; 16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;; 16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;; 16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;; 16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;; 1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;; 1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;; 1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;; 1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;; 1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;; 1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;; 16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;; 16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;; 16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;; 16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;; 16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;; 16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;; 16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;; 16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;; 16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;; 16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;; 1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;; 1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;; 1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;; 1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;; 1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;; 1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;; 16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;; 16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;; 16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;; 16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;; 16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;; 16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;; 16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;; 16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;; 16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;; 16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;; 1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;; 1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;; 1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;; 1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;; 1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;; 1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;; 16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;; 16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;; 16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;; 16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;; 16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;; 16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;; 16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;; 16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;; 16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;; 16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;; 1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;; 1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;; 1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;; 1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;; 1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;; 1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;; 16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;; 16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;; 16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;; 16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;; 16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;; 16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;; 16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;; 16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;; 16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;; 16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;; 1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;; 1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;; 1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;; 1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;; 1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;; 1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;; 16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;; 16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;; 16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;; 16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;; 16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;; 16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;; 16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;; 16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;; 16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;; 16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;; 1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;; 1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;; 1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;; 1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;; 1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;; 1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;; 16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;; 16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;; 16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;; 16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;; 16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;; 16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;; 16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;; 16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;; 16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;; 16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;; 1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;; 1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;; 1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;; 1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;; 1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;; 1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;; 168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;; 168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;; 168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;; 168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;; 168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;; 168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;; 168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;; 168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;; 168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;; 168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;; 168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;; 168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;; 168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;; 168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;; 168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;; 168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;; 168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;; 168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;; 168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;; 168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;; 168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;; 168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;; 168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;; 168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;; 168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;; 168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;; 168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;; 168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;; 168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;; 168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;; 168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;; 168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;; 168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;; 168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;; 168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;; 168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;; 168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;; 168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;; 168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;; 168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;; 168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;; 168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;; 168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;; 168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;; 168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;; 168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;; 168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;; 168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;; 168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;; 168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;; 168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;; 168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;; 168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;; 168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;; 168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;; 168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;; 168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;; 168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;; 168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;; 168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;; 168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;; 168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;; 168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;; 168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;; 168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;; 168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;; 168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;; 168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;; 168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;; 168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;; 168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;; 168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;; 168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;; 168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;; 168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;; 168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;; 168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;; 168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;; 168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;; 168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;; 168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;; 168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;; 168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;; 168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;; 168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;; 168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;; 168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;; 168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;; 168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;; 168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;; 168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;; 168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;; 168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;; 168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;; 168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;; 168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;; 16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;; 16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;; 16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;; 16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;; 16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;; 16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;; 16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;; 16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;; 16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;; 16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;; 1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;; 1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;; 1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;; 1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;; 1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;; 1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;; 16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;; 16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;; 16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;; 16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;; 16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;; 16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;; 16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;; 16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;; 16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;; 16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;; 1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;; 1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;; 1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;; 1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;; 1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;; 1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;; 16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;; 16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;; 16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;; 16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;; 16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;; 16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;; 16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;; 16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;; 16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;; 16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;; 1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;; 1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;; 1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;; 1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;; 1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;; 1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;; 16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;; 16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;; 16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;; 16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;; 16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;; 16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;; 16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;; 16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;; 16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;; 16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;; 1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;; 1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;; 1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;; 1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;; 1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;; 1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;; 16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;; 16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;; 16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;; 16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;; 16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;; 16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;; 16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;; 16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;; 16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;; 16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;; 1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;; 1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;; 1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;; 1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;; 1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;; 1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;; 16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;; 16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;; 16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;; 16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;; 16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;; 16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;; 16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;; 16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;; 16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;; 16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;; 1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;; 1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;; 1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;; 1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;; 1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;; 1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;; 16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;; 16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;; 16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;; 16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;; 16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;; 16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;; 16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;; 16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;; 16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;; 16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;; 1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;; 1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;; 1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;; 1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;; 1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;; 1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;; 16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;; 16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;; 16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;; 16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;; 16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;; 16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;; 16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;; 16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;; 16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;; 16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;; 1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;; 1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;; 1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;; 1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;; 1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;; 1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;; 16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;; 16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;; 16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;; 16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;; 16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;; 16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;; 16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;; 16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;; 16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;; 16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;; 1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;; 1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;; 1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;; 1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;; 1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;; 1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;; 16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;; 16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;; 16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;; 16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;; 16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;; 16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;; 16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;; 16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;; 16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;; 16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;; 1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;; 1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;; 1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;; 1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;; 1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;; 1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;; 169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;; 169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;; 169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;; 169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;; 169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;; 169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;; 169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;; 169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;; 169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;; 169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;; 169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;; 169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;; 169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;; 169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;; 169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;; 169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;; 169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;; 169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;; 169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;; 169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;; 169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;; 169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;; 169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;; 169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;; 169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;; 169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;; 169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;; 169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;; 169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;; 169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;; 169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;; 169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;; 169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;; 169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;; 169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;; 169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;; 169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;; 169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;; 169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;; 169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;; 169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;; 169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;; 169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;; 169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;; 169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;; 169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;; 169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;; 169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;; 169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;; 169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;; 169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;; 169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;; 169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;; 169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;; 169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;; 169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;; 169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;; 169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;; 169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;; 169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;; 169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;; 169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;; 169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;; 169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;; 169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;; 169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;; 169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;; 169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;; 169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;; 169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;; 169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;; 169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;; 169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;; 169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;; 169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;; 169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;; 169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;; 169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;; 169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;; 169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;; 169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;; 169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;; 169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;; 169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;; 169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;; 169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;; 169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;; 169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;; 169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;; 169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;; 169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;; 169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;; 169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;; 169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;; 169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;; 169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;; 16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;; 16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;; 16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;; 16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;; 16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;; 16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;; 16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;; 16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;; 16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;; 16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;; 16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;; 16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;; 16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;; 16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;; 16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;; 16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;; 16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;; 16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;; 16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;; 16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;; 16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;; 16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;; 16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;; 16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;; 16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;; 16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;; 16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;; 16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;; 16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;; 16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;; 16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;; 16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;; 16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;; 16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;; 16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;; 16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;; 16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;; 16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;; 16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;; 16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;; 16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;; 16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;; 16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;; 16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;; 16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;; 16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;; 16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;; 16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;; 16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;; 16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;; 16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;; 16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;; 16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;; 16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;; 16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;; 16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;; 16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;; 16A40;MRO LETTER TA;Lo;0;L;;;;;N;;;;; 16A41;MRO LETTER NGI;Lo;0;L;;;;;N;;;;; 16A42;MRO LETTER YO;Lo;0;L;;;;;N;;;;; 16A43;MRO LETTER MIM;Lo;0;L;;;;;N;;;;; 16A44;MRO LETTER BA;Lo;0;L;;;;;N;;;;; 16A45;MRO LETTER DA;Lo;0;L;;;;;N;;;;; 16A46;MRO LETTER A;Lo;0;L;;;;;N;;;;; 16A47;MRO LETTER PHI;Lo;0;L;;;;;N;;;;; 16A48;MRO LETTER KHAI;Lo;0;L;;;;;N;;;;; 16A49;MRO LETTER HAO;Lo;0;L;;;;;N;;;;; 16A4A;MRO LETTER DAI;Lo;0;L;;;;;N;;;;; 16A4B;MRO LETTER CHU;Lo;0;L;;;;;N;;;;; 16A4C;MRO LETTER KEAAE;Lo;0;L;;;;;N;;;;; 16A4D;MRO LETTER OL;Lo;0;L;;;;;N;;;;; 16A4E;MRO LETTER MAEM;Lo;0;L;;;;;N;;;;; 16A4F;MRO LETTER NIN;Lo;0;L;;;;;N;;;;; 16A50;MRO LETTER PA;Lo;0;L;;;;;N;;;;; 16A51;MRO LETTER OO;Lo;0;L;;;;;N;;;;; 16A52;MRO LETTER O;Lo;0;L;;;;;N;;;;; 16A53;MRO LETTER RO;Lo;0;L;;;;;N;;;;; 16A54;MRO LETTER SHI;Lo;0;L;;;;;N;;;;; 16A55;MRO LETTER THEA;Lo;0;L;;;;;N;;;;; 16A56;MRO LETTER EA;Lo;0;L;;;;;N;;;;; 16A57;MRO LETTER WA;Lo;0;L;;;;;N;;;;; 16A58;MRO LETTER E;Lo;0;L;;;;;N;;;;; 16A59;MRO LETTER KO;Lo;0;L;;;;;N;;;;; 16A5A;MRO LETTER LAN;Lo;0;L;;;;;N;;;;; 16A5B;MRO LETTER LA;Lo;0;L;;;;;N;;;;; 16A5C;MRO LETTER HAI;Lo;0;L;;;;;N;;;;; 16A5D;MRO LETTER RI;Lo;0;L;;;;;N;;;;; 16A5E;MRO LETTER TEK;Lo;0;L;;;;;N;;;;; 16A60;MRO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 16A61;MRO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 16A62;MRO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 16A63;MRO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 16A64;MRO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 16A65;MRO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 16A66;MRO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 16A67;MRO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 16A68;MRO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16A6E;MRO DANDA;Po;0;L;;;;;N;;;;; 16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;; 16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;; 16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;; 16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;; 16AD3;BASSA VAH LETTER FA;Lo;0;L;;;;;N;;;;; 16AD4;BASSA VAH LETTER MBE;Lo;0;L;;;;;N;;;;; 16AD5;BASSA VAH LETTER YIE;Lo;0;L;;;;;N;;;;; 16AD6;BASSA VAH LETTER GAH;Lo;0;L;;;;;N;;;;; 16AD7;BASSA VAH LETTER DHII;Lo;0;L;;;;;N;;;;; 16AD8;BASSA VAH LETTER KPAH;Lo;0;L;;;;;N;;;;; 16AD9;BASSA VAH LETTER JO;Lo;0;L;;;;;N;;;;; 16ADA;BASSA VAH LETTER HWAH;Lo;0;L;;;;;N;;;;; 16ADB;BASSA VAH LETTER WA;Lo;0;L;;;;;N;;;;; 16ADC;BASSA VAH LETTER ZO;Lo;0;L;;;;;N;;;;; 16ADD;BASSA VAH LETTER GBU;Lo;0;L;;;;;N;;;;; 16ADE;BASSA VAH LETTER DO;Lo;0;L;;;;;N;;;;; 16ADF;BASSA VAH LETTER CE;Lo;0;L;;;;;N;;;;; 16AE0;BASSA VAH LETTER UWU;Lo;0;L;;;;;N;;;;; 16AE1;BASSA VAH LETTER TO;Lo;0;L;;;;;N;;;;; 16AE2;BASSA VAH LETTER BA;Lo;0;L;;;;;N;;;;; 16AE3;BASSA VAH LETTER VU;Lo;0;L;;;;;N;;;;; 16AE4;BASSA VAH LETTER YEIN;Lo;0;L;;;;;N;;;;; 16AE5;BASSA VAH LETTER PA;Lo;0;L;;;;;N;;;;; 16AE6;BASSA VAH LETTER WADDA;Lo;0;L;;;;;N;;;;; 16AE7;BASSA VAH LETTER A;Lo;0;L;;;;;N;;;;; 16AE8;BASSA VAH LETTER O;Lo;0;L;;;;;N;;;;; 16AE9;BASSA VAH LETTER OO;Lo;0;L;;;;;N;;;;; 16AEA;BASSA VAH LETTER U;Lo;0;L;;;;;N;;;;; 16AEB;BASSA VAH LETTER EE;Lo;0;L;;;;;N;;;;; 16AEC;BASSA VAH LETTER E;Lo;0;L;;;;;N;;;;; 16AED;BASSA VAH LETTER I;Lo;0;L;;;;;N;;;;; 16AF0;BASSA VAH COMBINING HIGH TONE;Mn;1;NSM;;;;;N;;;;; 16AF1;BASSA VAH COMBINING LOW TONE;Mn;1;NSM;;;;;N;;;;; 16AF2;BASSA VAH COMBINING MID TONE;Mn;1;NSM;;;;;N;;;;; 16AF3;BASSA VAH COMBINING LOW-MID TONE;Mn;1;NSM;;;;;N;;;;; 16AF4;BASSA VAH COMBINING HIGH-LOW TONE;Mn;1;NSM;;;;;N;;;;; 16AF5;BASSA VAH FULL STOP;Po;0;L;;;;;N;;;;; 16B00;PAHAWH HMONG VOWEL KEEB;Lo;0;L;;;;;N;;;;; 16B01;PAHAWH HMONG VOWEL KEEV;Lo;0;L;;;;;N;;;;; 16B02;PAHAWH HMONG VOWEL KIB;Lo;0;L;;;;;N;;;;; 16B03;PAHAWH HMONG VOWEL KIV;Lo;0;L;;;;;N;;;;; 16B04;PAHAWH HMONG VOWEL KAUB;Lo;0;L;;;;;N;;;;; 16B05;PAHAWH HMONG VOWEL KAUV;Lo;0;L;;;;;N;;;;; 16B06;PAHAWH HMONG VOWEL KUB;Lo;0;L;;;;;N;;;;; 16B07;PAHAWH HMONG VOWEL KUV;Lo;0;L;;;;;N;;;;; 16B08;PAHAWH HMONG VOWEL KEB;Lo;0;L;;;;;N;;;;; 16B09;PAHAWH HMONG VOWEL KEV;Lo;0;L;;;;;N;;;;; 16B0A;PAHAWH HMONG VOWEL KAIB;Lo;0;L;;;;;N;;;;; 16B0B;PAHAWH HMONG VOWEL KAIV;Lo;0;L;;;;;N;;;;; 16B0C;PAHAWH HMONG VOWEL KOOB;Lo;0;L;;;;;N;;;;; 16B0D;PAHAWH HMONG VOWEL KOOV;Lo;0;L;;;;;N;;;;; 16B0E;PAHAWH HMONG VOWEL KAWB;Lo;0;L;;;;;N;;;;; 16B0F;PAHAWH HMONG VOWEL KAWV;Lo;0;L;;;;;N;;;;; 16B10;PAHAWH HMONG VOWEL KUAB;Lo;0;L;;;;;N;;;;; 16B11;PAHAWH HMONG VOWEL KUAV;Lo;0;L;;;;;N;;;;; 16B12;PAHAWH HMONG VOWEL KOB;Lo;0;L;;;;;N;;;;; 16B13;PAHAWH HMONG VOWEL KOV;Lo;0;L;;;;;N;;;;; 16B14;PAHAWH HMONG VOWEL KIAB;Lo;0;L;;;;;N;;;;; 16B15;PAHAWH HMONG VOWEL KIAV;Lo;0;L;;;;;N;;;;; 16B16;PAHAWH HMONG VOWEL KAB;Lo;0;L;;;;;N;;;;; 16B17;PAHAWH HMONG VOWEL KAV;Lo;0;L;;;;;N;;;;; 16B18;PAHAWH HMONG VOWEL KWB;Lo;0;L;;;;;N;;;;; 16B19;PAHAWH HMONG VOWEL KWV;Lo;0;L;;;;;N;;;;; 16B1A;PAHAWH HMONG VOWEL KAAB;Lo;0;L;;;;;N;;;;; 16B1B;PAHAWH HMONG VOWEL KAAV;Lo;0;L;;;;;N;;;;; 16B1C;PAHAWH HMONG CONSONANT VAU;Lo;0;L;;;;;N;;;;; 16B1D;PAHAWH HMONG CONSONANT NTSAU;Lo;0;L;;;;;N;;;;; 16B1E;PAHAWH HMONG CONSONANT LAU;Lo;0;L;;;;;N;;;;; 16B1F;PAHAWH HMONG CONSONANT HAU;Lo;0;L;;;;;N;;;;; 16B20;PAHAWH HMONG CONSONANT NLAU;Lo;0;L;;;;;N;;;;; 16B21;PAHAWH HMONG CONSONANT RAU;Lo;0;L;;;;;N;;;;; 16B22;PAHAWH HMONG CONSONANT NKAU;Lo;0;L;;;;;N;;;;; 16B23;PAHAWH HMONG CONSONANT QHAU;Lo;0;L;;;;;N;;;;; 16B24;PAHAWH HMONG CONSONANT YAU;Lo;0;L;;;;;N;;;;; 16B25;PAHAWH HMONG CONSONANT HLAU;Lo;0;L;;;;;N;;;;; 16B26;PAHAWH HMONG CONSONANT MAU;Lo;0;L;;;;;N;;;;; 16B27;PAHAWH HMONG CONSONANT CHAU;Lo;0;L;;;;;N;;;;; 16B28;PAHAWH HMONG CONSONANT NCHAU;Lo;0;L;;;;;N;;;;; 16B29;PAHAWH HMONG CONSONANT HNAU;Lo;0;L;;;;;N;;;;; 16B2A;PAHAWH HMONG CONSONANT PLHAU;Lo;0;L;;;;;N;;;;; 16B2B;PAHAWH HMONG CONSONANT NTHAU;Lo;0;L;;;;;N;;;;; 16B2C;PAHAWH HMONG CONSONANT NAU;Lo;0;L;;;;;N;;;;; 16B2D;PAHAWH HMONG CONSONANT AU;Lo;0;L;;;;;N;;;;; 16B2E;PAHAWH HMONG CONSONANT XAU;Lo;0;L;;;;;N;;;;; 16B2F;PAHAWH HMONG CONSONANT CAU;Lo;0;L;;;;;N;;;;; 16B30;PAHAWH HMONG MARK CIM TUB;Mn;230;NSM;;;;;N;;;;; 16B31;PAHAWH HMONG MARK CIM SO;Mn;230;NSM;;;;;N;;;;; 16B32;PAHAWH HMONG MARK CIM KES;Mn;230;NSM;;;;;N;;;;; 16B33;PAHAWH HMONG MARK CIM KHAV;Mn;230;NSM;;;;;N;;;;; 16B34;PAHAWH HMONG MARK CIM SUAM;Mn;230;NSM;;;;;N;;;;; 16B35;PAHAWH HMONG MARK CIM HOM;Mn;230;NSM;;;;;N;;;;; 16B36;PAHAWH HMONG MARK CIM TAUM;Mn;230;NSM;;;;;N;;;;; 16B37;PAHAWH HMONG SIGN VOS THOM;Po;0;L;;;;;N;;;;; 16B38;PAHAWH HMONG SIGN VOS TSHAB CEEB;Po;0;L;;;;;N;;;;; 16B39;PAHAWH HMONG SIGN CIM CHEEM;Po;0;L;;;;;N;;;;; 16B3A;PAHAWH HMONG SIGN VOS THIAB;Po;0;L;;;;;N;;;;; 16B3B;PAHAWH HMONG SIGN VOS FEEM;Po;0;L;;;;;N;;;;; 16B3C;PAHAWH HMONG SIGN XYEEM NTXIV;So;0;L;;;;;N;;;;; 16B3D;PAHAWH HMONG SIGN XYEEM RHO;So;0;L;;;;;N;;;;; 16B3E;PAHAWH HMONG SIGN XYEEM TOV;So;0;L;;;;;N;;;;; 16B3F;PAHAWH HMONG SIGN XYEEM FAIB;So;0;L;;;;;N;;;;; 16B40;PAHAWH HMONG SIGN VOS SEEV;Lm;0;L;;;;;N;;;;; 16B41;PAHAWH HMONG SIGN MEEJ SUAB;Lm;0;L;;;;;N;;;;; 16B42;PAHAWH HMONG SIGN VOS NRUA;Lm;0;L;;;;;N;;;;; 16B43;PAHAWH HMONG SIGN IB YAM;Lm;0;L;;;;;N;;;;; 16B44;PAHAWH HMONG SIGN XAUS;Po;0;L;;;;;N;;;;; 16B45;PAHAWH HMONG SIGN CIM TSOV ROG;So;0;L;;;;;N;;;;; 16B50;PAHAWH HMONG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 16B51;PAHAWH HMONG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 16B52;PAHAWH HMONG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 16B53;PAHAWH HMONG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 16B54;PAHAWH HMONG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 16B55;PAHAWH HMONG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 16B56;PAHAWH HMONG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 16B57;PAHAWH HMONG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 16B58;PAHAWH HMONG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 16B59;PAHAWH HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16B5B;PAHAWH HMONG NUMBER TENS;No;0;L;;;;10;N;;;;; 16B5C;PAHAWH HMONG NUMBER HUNDREDS;No;0;L;;;;100;N;;;;; 16B5D;PAHAWH HMONG NUMBER TEN THOUSANDS;No;0;L;;;;10000;N;;;;; 16B5E;PAHAWH HMONG NUMBER MILLIONS;No;0;L;;;;1000000;N;;;;; 16B5F;PAHAWH HMONG NUMBER HUNDRED MILLIONS;No;0;L;;;;100000000;N;;;;; 16B60;PAHAWH HMONG NUMBER TEN BILLIONS;No;0;L;;;;10000000000;N;;;;; 16B61;PAHAWH HMONG NUMBER TRILLIONS;No;0;L;;;;1000000000000;N;;;;; 16B63;PAHAWH HMONG SIGN VOS LUB;Lo;0;L;;;;;N;;;;; 16B64;PAHAWH HMONG SIGN XYOO;Lo;0;L;;;;;N;;;;; 16B65;PAHAWH HMONG SIGN HLI;Lo;0;L;;;;;N;;;;; 16B66;PAHAWH HMONG SIGN THIRD-STAGE HLI;Lo;0;L;;;;;N;;;;; 16B67;PAHAWH HMONG SIGN ZWJ THAJ;Lo;0;L;;;;;N;;;;; 16B68;PAHAWH HMONG SIGN HNUB;Lo;0;L;;;;;N;;;;; 16B69;PAHAWH HMONG SIGN NQIG;Lo;0;L;;;;;N;;;;; 16B6A;PAHAWH HMONG SIGN XIAB;Lo;0;L;;;;;N;;;;; 16B6B;PAHAWH HMONG SIGN NTUJ;Lo;0;L;;;;;N;;;;; 16B6C;PAHAWH HMONG SIGN AV;Lo;0;L;;;;;N;;;;; 16B6D;PAHAWH HMONG SIGN TXHEEJ CEEV;Lo;0;L;;;;;N;;;;; 16B6E;PAHAWH HMONG SIGN MEEJ TSEEB;Lo;0;L;;;;;N;;;;; 16B6F;PAHAWH HMONG SIGN TAU;Lo;0;L;;;;;N;;;;; 16B70;PAHAWH HMONG SIGN LOS;Lo;0;L;;;;;N;;;;; 16B71;PAHAWH HMONG SIGN MUS;Lo;0;L;;;;;N;;;;; 16B72;PAHAWH HMONG SIGN CIM HAIS LUS NTOG NTOG;Lo;0;L;;;;;N;;;;; 16B73;PAHAWH HMONG SIGN CIM CUAM TSHOOJ;Lo;0;L;;;;;N;;;;; 16B74;PAHAWH HMONG SIGN CIM TXWV;Lo;0;L;;;;;N;;;;; 16B75;PAHAWH HMONG SIGN CIM TXWV CHWV;Lo;0;L;;;;;N;;;;; 16B76;PAHAWH HMONG SIGN CIM PUB DAWB;Lo;0;L;;;;;N;;;;; 16B77;PAHAWH HMONG SIGN CIM NRES TOS;Lo;0;L;;;;;N;;;;; 16B7D;PAHAWH HMONG CLAN SIGN TSHEEJ;Lo;0;L;;;;;N;;;;; 16B7E;PAHAWH HMONG CLAN SIGN YEEG;Lo;0;L;;;;;N;;;;; 16B7F;PAHAWH HMONG CLAN SIGN LIS;Lo;0;L;;;;;N;;;;; 16B80;PAHAWH HMONG CLAN SIGN LAUJ;Lo;0;L;;;;;N;;;;; 16B81;PAHAWH HMONG CLAN SIGN XYOOJ;Lo;0;L;;;;;N;;;;; 16B82;PAHAWH HMONG CLAN SIGN KOO;Lo;0;L;;;;;N;;;;; 16B83;PAHAWH HMONG CLAN SIGN HAWJ;Lo;0;L;;;;;N;;;;; 16B84;PAHAWH HMONG CLAN SIGN MUAS;Lo;0;L;;;;;N;;;;; 16B85;PAHAWH HMONG CLAN SIGN THOJ;Lo;0;L;;;;;N;;;;; 16B86;PAHAWH HMONG CLAN SIGN TSAB;Lo;0;L;;;;;N;;;;; 16B87;PAHAWH HMONG CLAN SIGN PHAB;Lo;0;L;;;;;N;;;;; 16B88;PAHAWH HMONG CLAN SIGN KHAB;Lo;0;L;;;;;N;;;;; 16B89;PAHAWH HMONG CLAN SIGN HAM;Lo;0;L;;;;;N;;;;; 16B8A;PAHAWH HMONG CLAN SIGN VAJ;Lo;0;L;;;;;N;;;;; 16B8B;PAHAWH HMONG CLAN SIGN FAJ;Lo;0;L;;;;;N;;;;; 16B8C;PAHAWH HMONG CLAN SIGN YAJ;Lo;0;L;;;;;N;;;;; 16B8D;PAHAWH HMONG CLAN SIGN TSWB;Lo;0;L;;;;;N;;;;; 16B8E;PAHAWH HMONG CLAN SIGN KWM;Lo;0;L;;;;;N;;;;; 16B8F;PAHAWH HMONG CLAN SIGN VWJ;Lo;0;L;;;;;N;;;;; 16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;; 16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;; 16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;; 16F03;MIAO LETTER PLA;Lo;0;L;;;;;N;;;;; 16F04;MIAO LETTER MA;Lo;0;L;;;;;N;;;;; 16F05;MIAO LETTER MHA;Lo;0;L;;;;;N;;;;; 16F06;MIAO LETTER ARCHAIC MA;Lo;0;L;;;;;N;;;;; 16F07;MIAO LETTER FA;Lo;0;L;;;;;N;;;;; 16F08;MIAO LETTER VA;Lo;0;L;;;;;N;;;;; 16F09;MIAO LETTER VFA;Lo;0;L;;;;;N;;;;; 16F0A;MIAO LETTER TA;Lo;0;L;;;;;N;;;;; 16F0B;MIAO LETTER DA;Lo;0;L;;;;;N;;;;; 16F0C;MIAO LETTER YI TTA;Lo;0;L;;;;;N;;;;; 16F0D;MIAO LETTER YI TA;Lo;0;L;;;;;N;;;;; 16F0E;MIAO LETTER TTA;Lo;0;L;;;;;N;;;;; 16F0F;MIAO LETTER DDA;Lo;0;L;;;;;N;;;;; 16F10;MIAO LETTER NA;Lo;0;L;;;;;N;;;;; 16F11;MIAO LETTER NHA;Lo;0;L;;;;;N;;;;; 16F12;MIAO LETTER YI NNA;Lo;0;L;;;;;N;;;;; 16F13;MIAO LETTER ARCHAIC NA;Lo;0;L;;;;;N;;;;; 16F14;MIAO LETTER NNA;Lo;0;L;;;;;N;;;;; 16F15;MIAO LETTER NNHA;Lo;0;L;;;;;N;;;;; 16F16;MIAO LETTER LA;Lo;0;L;;;;;N;;;;; 16F17;MIAO LETTER LYA;Lo;0;L;;;;;N;;;;; 16F18;MIAO LETTER LHA;Lo;0;L;;;;;N;;;;; 16F19;MIAO LETTER LHYA;Lo;0;L;;;;;N;;;;; 16F1A;MIAO LETTER TLHA;Lo;0;L;;;;;N;;;;; 16F1B;MIAO LETTER DLHA;Lo;0;L;;;;;N;;;;; 16F1C;MIAO LETTER TLHYA;Lo;0;L;;;;;N;;;;; 16F1D;MIAO LETTER DLHYA;Lo;0;L;;;;;N;;;;; 16F1E;MIAO LETTER KA;Lo;0;L;;;;;N;;;;; 16F1F;MIAO LETTER GA;Lo;0;L;;;;;N;;;;; 16F20;MIAO LETTER YI KA;Lo;0;L;;;;;N;;;;; 16F21;MIAO LETTER QA;Lo;0;L;;;;;N;;;;; 16F22;MIAO LETTER QGA;Lo;0;L;;;;;N;;;;; 16F23;MIAO LETTER NGA;Lo;0;L;;;;;N;;;;; 16F24;MIAO LETTER NGHA;Lo;0;L;;;;;N;;;;; 16F25;MIAO LETTER ARCHAIC NGA;Lo;0;L;;;;;N;;;;; 16F26;MIAO LETTER HA;Lo;0;L;;;;;N;;;;; 16F27;MIAO LETTER XA;Lo;0;L;;;;;N;;;;; 16F28;MIAO LETTER GHA;Lo;0;L;;;;;N;;;;; 16F29;MIAO LETTER GHHA;Lo;0;L;;;;;N;;;;; 16F2A;MIAO LETTER TSSA;Lo;0;L;;;;;N;;;;; 16F2B;MIAO LETTER DZZA;Lo;0;L;;;;;N;;;;; 16F2C;MIAO LETTER NYA;Lo;0;L;;;;;N;;;;; 16F2D;MIAO LETTER NYHA;Lo;0;L;;;;;N;;;;; 16F2E;MIAO LETTER TSHA;Lo;0;L;;;;;N;;;;; 16F2F;MIAO LETTER DZHA;Lo;0;L;;;;;N;;;;; 16F30;MIAO LETTER YI TSHA;Lo;0;L;;;;;N;;;;; 16F31;MIAO LETTER YI DZHA;Lo;0;L;;;;;N;;;;; 16F32;MIAO LETTER REFORMED TSHA;Lo;0;L;;;;;N;;;;; 16F33;MIAO LETTER SHA;Lo;0;L;;;;;N;;;;; 16F34;MIAO LETTER SSA;Lo;0;L;;;;;N;;;;; 16F35;MIAO LETTER ZHA;Lo;0;L;;;;;N;;;;; 16F36;MIAO LETTER ZSHA;Lo;0;L;;;;;N;;;;; 16F37;MIAO LETTER TSA;Lo;0;L;;;;;N;;;;; 16F38;MIAO LETTER DZA;Lo;0;L;;;;;N;;;;; 16F39;MIAO LETTER YI TSA;Lo;0;L;;;;;N;;;;; 16F3A;MIAO LETTER SA;Lo;0;L;;;;;N;;;;; 16F3B;MIAO LETTER ZA;Lo;0;L;;;;;N;;;;; 16F3C;MIAO LETTER ZSA;Lo;0;L;;;;;N;;;;; 16F3D;MIAO LETTER ZZA;Lo;0;L;;;;;N;;;;; 16F3E;MIAO LETTER ZZSA;Lo;0;L;;;;;N;;;;; 16F3F;MIAO LETTER ARCHAIC ZZA;Lo;0;L;;;;;N;;;;; 16F40;MIAO LETTER ZZYA;Lo;0;L;;;;;N;;;;; 16F41;MIAO LETTER ZZSYA;Lo;0;L;;;;;N;;;;; 16F42;MIAO LETTER WA;Lo;0;L;;;;;N;;;;; 16F43;MIAO LETTER AH;Lo;0;L;;;;;N;;;;; 16F44;MIAO LETTER HHA;Lo;0;L;;;;;N;;;;; 16F50;MIAO LETTER NASALIZATION;Lo;0;L;;;;;N;;;;; 16F51;MIAO SIGN ASPIRATION;Mc;0;L;;;;;N;;;;; 16F52;MIAO SIGN REFORMED VOICING;Mc;0;L;;;;;N;;;;; 16F53;MIAO SIGN REFORMED ASPIRATION;Mc;0;L;;;;;N;;;;; 16F54;MIAO VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 16F55;MIAO VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 16F56;MIAO VOWEL SIGN AHH;Mc;0;L;;;;;N;;;;; 16F57;MIAO VOWEL SIGN AN;Mc;0;L;;;;;N;;;;; 16F58;MIAO VOWEL SIGN ANG;Mc;0;L;;;;;N;;;;; 16F59;MIAO VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 16F5A;MIAO VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 16F5B;MIAO VOWEL SIGN WO;Mc;0;L;;;;;N;;;;; 16F5C;MIAO VOWEL SIGN W;Mc;0;L;;;;;N;;;;; 16F5D;MIAO VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 16F5E;MIAO VOWEL SIGN EN;Mc;0;L;;;;;N;;;;; 16F5F;MIAO VOWEL SIGN ENG;Mc;0;L;;;;;N;;;;; 16F60;MIAO VOWEL SIGN OEY;Mc;0;L;;;;;N;;;;; 16F61;MIAO VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 16F62;MIAO VOWEL SIGN IA;Mc;0;L;;;;;N;;;;; 16F63;MIAO VOWEL SIGN IAN;Mc;0;L;;;;;N;;;;; 16F64;MIAO VOWEL SIGN IANG;Mc;0;L;;;;;N;;;;; 16F65;MIAO VOWEL SIGN IO;Mc;0;L;;;;;N;;;;; 16F66;MIAO VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 16F67;MIAO VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 16F68;MIAO VOWEL SIGN IU;Mc;0;L;;;;;N;;;;; 16F69;MIAO VOWEL SIGN ING;Mc;0;L;;;;;N;;;;; 16F6A;MIAO VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 16F6B;MIAO VOWEL SIGN UA;Mc;0;L;;;;;N;;;;; 16F6C;MIAO VOWEL SIGN UAN;Mc;0;L;;;;;N;;;;; 16F6D;MIAO VOWEL SIGN UANG;Mc;0;L;;;;;N;;;;; 16F6E;MIAO VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 16F6F;MIAO VOWEL SIGN UEI;Mc;0;L;;;;;N;;;;; 16F70;MIAO VOWEL SIGN UNG;Mc;0;L;;;;;N;;;;; 16F71;MIAO VOWEL SIGN Y;Mc;0;L;;;;;N;;;;; 16F72;MIAO VOWEL SIGN YI;Mc;0;L;;;;;N;;;;; 16F73;MIAO VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 16F74;MIAO VOWEL SIGN AEE;Mc;0;L;;;;;N;;;;; 16F75;MIAO VOWEL SIGN ERR;Mc;0;L;;;;;N;;;;; 16F76;MIAO VOWEL SIGN ROUNDED ERR;Mc;0;L;;;;;N;;;;; 16F77;MIAO VOWEL SIGN ER;Mc;0;L;;;;;N;;;;; 16F78;MIAO VOWEL SIGN ROUNDED ER;Mc;0;L;;;;;N;;;;; 16F79;MIAO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 16F7A;MIAO VOWEL SIGN EI;Mc;0;L;;;;;N;;;;; 16F7B;MIAO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 16F7C;MIAO VOWEL SIGN OU;Mc;0;L;;;;;N;;;;; 16F7D;MIAO VOWEL SIGN N;Mc;0;L;;;;;N;;;;; 16F7E;MIAO VOWEL SIGN NG;Mc;0;L;;;;;N;;;;; 16F8F;MIAO TONE RIGHT;Mn;0;NSM;;;;;N;;;;; 16F90;MIAO TONE TOP RIGHT;Mn;0;NSM;;;;;N;;;;; 16F91;MIAO TONE ABOVE;Mn;0;NSM;;;;;N;;;;; 16F92;MIAO TONE BELOW;Mn;0;NSM;;;;;N;;;;; 16F93;MIAO LETTER TONE-2;Lm;0;L;;;;;N;;;;; 16F94;MIAO LETTER TONE-3;Lm;0;L;;;;;N;;;;; 16F95;MIAO LETTER TONE-4;Lm;0;L;;;;;N;;;;; 16F96;MIAO LETTER TONE-5;Lm;0;L;;;;;N;;;;; 16F97;MIAO LETTER TONE-6;Lm;0;L;;;;;N;;;;; 16F98;MIAO LETTER TONE-7;Lm;0;L;;;;;N;;;;; 16F99;MIAO LETTER TONE-8;Lm;0;L;;;;;N;;;;; 16F9A;MIAO LETTER REFORMED TONE-1;Lm;0;L;;;;;N;;;;; 16F9B;MIAO LETTER REFORMED TONE-2;Lm;0;L;;;;;N;;;;; 16F9C;MIAO LETTER REFORMED TONE-4;Lm;0;L;;;;;N;;;;; 16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;; 16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; 16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; 1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; 1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; 1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; 1BC03;DUPLOYAN LETTER T;Lo;0;L;;;;;N;;;;; 1BC04;DUPLOYAN LETTER F;Lo;0;L;;;;;N;;;;; 1BC05;DUPLOYAN LETTER K;Lo;0;L;;;;;N;;;;; 1BC06;DUPLOYAN LETTER L;Lo;0;L;;;;;N;;;;; 1BC07;DUPLOYAN LETTER B;Lo;0;L;;;;;N;;;;; 1BC08;DUPLOYAN LETTER D;Lo;0;L;;;;;N;;;;; 1BC09;DUPLOYAN LETTER V;Lo;0;L;;;;;N;;;;; 1BC0A;DUPLOYAN LETTER G;Lo;0;L;;;;;N;;;;; 1BC0B;DUPLOYAN LETTER R;Lo;0;L;;;;;N;;;;; 1BC0C;DUPLOYAN LETTER P N;Lo;0;L;;;;;N;;;;; 1BC0D;DUPLOYAN LETTER D S;Lo;0;L;;;;;N;;;;; 1BC0E;DUPLOYAN LETTER F N;Lo;0;L;;;;;N;;;;; 1BC0F;DUPLOYAN LETTER K M;Lo;0;L;;;;;N;;;;; 1BC10;DUPLOYAN LETTER R S;Lo;0;L;;;;;N;;;;; 1BC11;DUPLOYAN LETTER TH;Lo;0;L;;;;;N;;;;; 1BC12;DUPLOYAN LETTER SLOAN DH;Lo;0;L;;;;;N;;;;; 1BC13;DUPLOYAN LETTER DH;Lo;0;L;;;;;N;;;;; 1BC14;DUPLOYAN LETTER KK;Lo;0;L;;;;;N;;;;; 1BC15;DUPLOYAN LETTER SLOAN J;Lo;0;L;;;;;N;;;;; 1BC16;DUPLOYAN LETTER HL;Lo;0;L;;;;;N;;;;; 1BC17;DUPLOYAN LETTER LH;Lo;0;L;;;;;N;;;;; 1BC18;DUPLOYAN LETTER RH;Lo;0;L;;;;;N;;;;; 1BC19;DUPLOYAN LETTER M;Lo;0;L;;;;;N;;;;; 1BC1A;DUPLOYAN LETTER N;Lo;0;L;;;;;N;;;;; 1BC1B;DUPLOYAN LETTER J;Lo;0;L;;;;;N;;;;; 1BC1C;DUPLOYAN LETTER S;Lo;0;L;;;;;N;;;;; 1BC1D;DUPLOYAN LETTER M N;Lo;0;L;;;;;N;;;;; 1BC1E;DUPLOYAN LETTER N M;Lo;0;L;;;;;N;;;;; 1BC1F;DUPLOYAN LETTER J M;Lo;0;L;;;;;N;;;;; 1BC20;DUPLOYAN LETTER S J;Lo;0;L;;;;;N;;;;; 1BC21;DUPLOYAN LETTER M WITH DOT;Lo;0;L;;;;;N;;;;; 1BC22;DUPLOYAN LETTER N WITH DOT;Lo;0;L;;;;;N;;;;; 1BC23;DUPLOYAN LETTER J WITH DOT;Lo;0;L;;;;;N;;;;; 1BC24;DUPLOYAN LETTER J WITH DOTS INSIDE AND ABOVE;Lo;0;L;;;;;N;;;;; 1BC25;DUPLOYAN LETTER S WITH DOT;Lo;0;L;;;;;N;;;;; 1BC26;DUPLOYAN LETTER S WITH DOT BELOW;Lo;0;L;;;;;N;;;;; 1BC27;DUPLOYAN LETTER M S;Lo;0;L;;;;;N;;;;; 1BC28;DUPLOYAN LETTER N S;Lo;0;L;;;;;N;;;;; 1BC29;DUPLOYAN LETTER J S;Lo;0;L;;;;;N;;;;; 1BC2A;DUPLOYAN LETTER S S;Lo;0;L;;;;;N;;;;; 1BC2B;DUPLOYAN LETTER M N S;Lo;0;L;;;;;N;;;;; 1BC2C;DUPLOYAN LETTER N M S;Lo;0;L;;;;;N;;;;; 1BC2D;DUPLOYAN LETTER J M S;Lo;0;L;;;;;N;;;;; 1BC2E;DUPLOYAN LETTER S J S;Lo;0;L;;;;;N;;;;; 1BC2F;DUPLOYAN LETTER J S WITH DOT;Lo;0;L;;;;;N;;;;; 1BC30;DUPLOYAN LETTER J N;Lo;0;L;;;;;N;;;;; 1BC31;DUPLOYAN LETTER J N S;Lo;0;L;;;;;N;;;;; 1BC32;DUPLOYAN LETTER S T;Lo;0;L;;;;;N;;;;; 1BC33;DUPLOYAN LETTER S T R;Lo;0;L;;;;;N;;;;; 1BC34;DUPLOYAN LETTER S P;Lo;0;L;;;;;N;;;;; 1BC35;DUPLOYAN LETTER S P R;Lo;0;L;;;;;N;;;;; 1BC36;DUPLOYAN LETTER T S;Lo;0;L;;;;;N;;;;; 1BC37;DUPLOYAN LETTER T R S;Lo;0;L;;;;;N;;;;; 1BC38;DUPLOYAN LETTER W;Lo;0;L;;;;;N;;;;; 1BC39;DUPLOYAN LETTER WH;Lo;0;L;;;;;N;;;;; 1BC3A;DUPLOYAN LETTER W R;Lo;0;L;;;;;N;;;;; 1BC3B;DUPLOYAN LETTER S N;Lo;0;L;;;;;N;;;;; 1BC3C;DUPLOYAN LETTER S M;Lo;0;L;;;;;N;;;;; 1BC3D;DUPLOYAN LETTER K R S;Lo;0;L;;;;;N;;;;; 1BC3E;DUPLOYAN LETTER G R S;Lo;0;L;;;;;N;;;;; 1BC3F;DUPLOYAN LETTER S K;Lo;0;L;;;;;N;;;;; 1BC40;DUPLOYAN LETTER S K R;Lo;0;L;;;;;N;;;;; 1BC41;DUPLOYAN LETTER A;Lo;0;L;;;;;N;;;;; 1BC42;DUPLOYAN LETTER SLOAN OW;Lo;0;L;;;;;N;;;;; 1BC43;DUPLOYAN LETTER OA;Lo;0;L;;;;;N;;;;; 1BC44;DUPLOYAN LETTER O;Lo;0;L;;;;;N;;;;; 1BC45;DUPLOYAN LETTER AOU;Lo;0;L;;;;;N;;;;; 1BC46;DUPLOYAN LETTER I;Lo;0;L;;;;;N;;;;; 1BC47;DUPLOYAN LETTER E;Lo;0;L;;;;;N;;;;; 1BC48;DUPLOYAN LETTER IE;Lo;0;L;;;;;N;;;;; 1BC49;DUPLOYAN LETTER SHORT I;Lo;0;L;;;;;N;;;;; 1BC4A;DUPLOYAN LETTER UI;Lo;0;L;;;;;N;;;;; 1BC4B;DUPLOYAN LETTER EE;Lo;0;L;;;;;N;;;;; 1BC4C;DUPLOYAN LETTER SLOAN EH;Lo;0;L;;;;;N;;;;; 1BC4D;DUPLOYAN LETTER ROMANIAN I;Lo;0;L;;;;;N;;;;; 1BC4E;DUPLOYAN LETTER SLOAN EE;Lo;0;L;;;;;N;;;;; 1BC4F;DUPLOYAN LETTER LONG I;Lo;0;L;;;;;N;;;;; 1BC50;DUPLOYAN LETTER YE;Lo;0;L;;;;;N;;;;; 1BC51;DUPLOYAN LETTER U;Lo;0;L;;;;;N;;;;; 1BC52;DUPLOYAN LETTER EU;Lo;0;L;;;;;N;;;;; 1BC53;DUPLOYAN LETTER XW;Lo;0;L;;;;;N;;;;; 1BC54;DUPLOYAN LETTER U N;Lo;0;L;;;;;N;;;;; 1BC55;DUPLOYAN LETTER LONG U;Lo;0;L;;;;;N;;;;; 1BC56;DUPLOYAN LETTER ROMANIAN U;Lo;0;L;;;;;N;;;;; 1BC57;DUPLOYAN LETTER UH;Lo;0;L;;;;;N;;;;; 1BC58;DUPLOYAN LETTER SLOAN U;Lo;0;L;;;;;N;;;;; 1BC59;DUPLOYAN LETTER OOH;Lo;0;L;;;;;N;;;;; 1BC5A;DUPLOYAN LETTER OW;Lo;0;L;;;;;N;;;;; 1BC5B;DUPLOYAN LETTER OU;Lo;0;L;;;;;N;;;;; 1BC5C;DUPLOYAN LETTER WA;Lo;0;L;;;;;N;;;;; 1BC5D;DUPLOYAN LETTER WO;Lo;0;L;;;;;N;;;;; 1BC5E;DUPLOYAN LETTER WI;Lo;0;L;;;;;N;;;;; 1BC5F;DUPLOYAN LETTER WEI;Lo;0;L;;;;;N;;;;; 1BC60;DUPLOYAN LETTER WOW;Lo;0;L;;;;;N;;;;; 1BC61;DUPLOYAN LETTER NASAL U;Lo;0;L;;;;;N;;;;; 1BC62;DUPLOYAN LETTER NASAL O;Lo;0;L;;;;;N;;;;; 1BC63;DUPLOYAN LETTER NASAL I;Lo;0;L;;;;;N;;;;; 1BC64;DUPLOYAN LETTER NASAL A;Lo;0;L;;;;;N;;;;; 1BC65;DUPLOYAN LETTER PERNIN AN;Lo;0;L;;;;;N;;;;; 1BC66;DUPLOYAN LETTER PERNIN AM;Lo;0;L;;;;;N;;;;; 1BC67;DUPLOYAN LETTER SLOAN EN;Lo;0;L;;;;;N;;;;; 1BC68;DUPLOYAN LETTER SLOAN AN;Lo;0;L;;;;;N;;;;; 1BC69;DUPLOYAN LETTER SLOAN ON;Lo;0;L;;;;;N;;;;; 1BC6A;DUPLOYAN LETTER VOCALIC M;Lo;0;L;;;;;N;;;;; 1BC70;DUPLOYAN AFFIX LEFT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC71;DUPLOYAN AFFIX MID HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC72;DUPLOYAN AFFIX RIGHT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC73;DUPLOYAN AFFIX LOW VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC74;DUPLOYAN AFFIX MID VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC75;DUPLOYAN AFFIX HIGH VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC76;DUPLOYAN AFFIX ATTACHED SECANT;Lo;0;L;;;;;N;;;;; 1BC77;DUPLOYAN AFFIX ATTACHED LEFT-TO-RIGHT SECANT;Lo;0;L;;;;;N;;;;; 1BC78;DUPLOYAN AFFIX ATTACHED TANGENT;Lo;0;L;;;;;N;;;;; 1BC79;DUPLOYAN AFFIX ATTACHED TAIL;Lo;0;L;;;;;N;;;;; 1BC7A;DUPLOYAN AFFIX ATTACHED E HOOK;Lo;0;L;;;;;N;;;;; 1BC7B;DUPLOYAN AFFIX ATTACHED I HOOK;Lo;0;L;;;;;N;;;;; 1BC7C;DUPLOYAN AFFIX ATTACHED TANGENT HOOK;Lo;0;L;;;;;N;;;;; 1BC80;DUPLOYAN AFFIX HIGH ACUTE;Lo;0;L;;;;;N;;;;; 1BC81;DUPLOYAN AFFIX HIGH TIGHT ACUTE;Lo;0;L;;;;;N;;;;; 1BC82;DUPLOYAN AFFIX HIGH GRAVE;Lo;0;L;;;;;N;;;;; 1BC83;DUPLOYAN AFFIX HIGH LONG GRAVE;Lo;0;L;;;;;N;;;;; 1BC84;DUPLOYAN AFFIX HIGH DOT;Lo;0;L;;;;;N;;;;; 1BC85;DUPLOYAN AFFIX HIGH CIRCLE;Lo;0;L;;;;;N;;;;; 1BC86;DUPLOYAN AFFIX HIGH LINE;Lo;0;L;;;;;N;;;;; 1BC87;DUPLOYAN AFFIX HIGH WAVE;Lo;0;L;;;;;N;;;;; 1BC88;DUPLOYAN AFFIX HIGH VERTICAL;Lo;0;L;;;;;N;;;;; 1BC90;DUPLOYAN AFFIX LOW ACUTE;Lo;0;L;;;;;N;;;;; 1BC91;DUPLOYAN AFFIX LOW TIGHT ACUTE;Lo;0;L;;;;;N;;;;; 1BC92;DUPLOYAN AFFIX LOW GRAVE;Lo;0;L;;;;;N;;;;; 1BC93;DUPLOYAN AFFIX LOW LONG GRAVE;Lo;0;L;;;;;N;;;;; 1BC94;DUPLOYAN AFFIX LOW DOT;Lo;0;L;;;;;N;;;;; 1BC95;DUPLOYAN AFFIX LOW CIRCLE;Lo;0;L;;;;;N;;;;; 1BC96;DUPLOYAN AFFIX LOW LINE;Lo;0;L;;;;;N;;;;; 1BC97;DUPLOYAN AFFIX LOW WAVE;Lo;0;L;;;;;N;;;;; 1BC98;DUPLOYAN AFFIX LOW VERTICAL;Lo;0;L;;;;;N;;;;; 1BC99;DUPLOYAN AFFIX LOW ARROW;Lo;0;L;;;;;N;;;;; 1BC9C;DUPLOYAN SIGN O WITH CROSS;So;0;L;;;;;N;;;;; 1BC9D;DUPLOYAN THICK LETTER SELECTOR;Mn;0;NSM;;;;;N;;;;; 1BC9E;DUPLOYAN DOUBLE MARK;Mn;1;NSM;;;;;N;;;;; 1BC9F;DUPLOYAN PUNCTUATION CHINOOK FULL STOP;Po;0;L;;;;;N;;;;; 1BCA0;SHORTHAND FORMAT LETTER OVERLAP;Cf;0;BN;;;;;N;;;;; 1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;; 1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;; 1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;; 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; 1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; 1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; 1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; 1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; 1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; 1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; 1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; 1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; 1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; 1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; 1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; 1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; 1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; 1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; 1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; 1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; 1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; 1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; 1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; 1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; 1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; 1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; 1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; 1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; 1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; 1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; 1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; 1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; 1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; 1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; 1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; 1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; 1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; 1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; 1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; 1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; 1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; 1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; 1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; 1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; 1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; 1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; 1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; 1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; 1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; 1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; 1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; 1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; 1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; 1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; 1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; 1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; 1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; 1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; 1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; 1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; 1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; 1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; 1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; 1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; 1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; 1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; 1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; 1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; 1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; 1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; 1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; 1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; 1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; 1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; 1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; 1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; 1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; 1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; 1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; 1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; 1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; 1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; 1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; 1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; 1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; 1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; 1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; 1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; 1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; 1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; 1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; 1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; 1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; 1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; 1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; 1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; 1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; 1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; 1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; 1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; 1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; 1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; 1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; 1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; 1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; 1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; 1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; 1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; 1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; 1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; 1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; 1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; 1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; 1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; 1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; 1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; 1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; 1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; 1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; 1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; 1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; 1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; 1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; 1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; 1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; 1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; 1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; 1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; 1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; 1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; 1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; 1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; 1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; 1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; 1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; 1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; 1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; 1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; 1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; 1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; 1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; 1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; 1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; 1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; 1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; 1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; 1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; 1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; 1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; 1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; 1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; 1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; 1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; 1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; 1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; 1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; 1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; 1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; 1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; 1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; 1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; 1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; 1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; 1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; 1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; 1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; 1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; 1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; 1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; 1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; 1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; 1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; 1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; 1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; 1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; 1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; 1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; 1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; 1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; 1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; 1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; 1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; 1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; 1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; 1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; 1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; 1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; 1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; 1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; 1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; 1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; 1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; 1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; 1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; 1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; 1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; 1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; 1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; 1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; 1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; 1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; 1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; 1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; 1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; 1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; 1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; 1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; 1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; 1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; 1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; 1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; 1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; 1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; 1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; 1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; 1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; 1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; 1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; 1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; 1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; 1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; 1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; 1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; 1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; 1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; 1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; 1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; 1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; 1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; 1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; 1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; 1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; 1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; 1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; 1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; 1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; 1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; 1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; 1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; 1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; 1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;; 1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; 1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; 1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; 1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; 1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; 1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; 1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; 1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; 1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; 1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; 1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; 1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; 1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; 1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; 1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; 1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; 1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; 1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; 1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; 1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; 1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; 1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; 1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; 1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; 1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; 1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; 1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; 1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; 1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; 1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; 1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; 1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; 1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; 1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; 1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; 1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; 1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; 1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; 1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; 1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; 1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; 1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; 1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; 1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; 1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; 1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; 1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; 1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; 1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; 1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; 1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; 1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; 1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; 1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; 1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; 1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; 1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; 1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; 1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; 1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; 1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; 1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; 1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; 1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; 1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; 1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; 1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; 1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; 1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; 1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; 1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; 1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; 1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; 1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; 1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; 1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; 1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; 1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; 1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; 1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; 1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; 1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; 1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; 1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; 1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; 1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; 1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; 1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; 1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; 1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; 1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; 1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; 1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; 1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; 1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; 1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; 1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; 1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; 1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; 1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; 1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; 1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; 1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; 1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; 1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; 1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; 1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; 1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; 1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; 1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; 1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; 1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; 1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; 1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; 1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; 1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; 1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; 1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; 1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; 1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; 1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; 1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; 1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; 1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; 1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; 1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; 1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; 1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; 1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; 1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; 1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; 1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; 1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; 1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; 1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; 1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; 1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; 1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; 1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; 1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; 1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; 1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; 1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; 1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; 1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; 1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; 1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; 1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; 1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; 1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; 1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; 1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; 1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; 1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; 1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; 1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; 1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;; 1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;; 1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;; 1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;; 1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;; 1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;; 1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;; 1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;; 1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;; 1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;; 1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;; 1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;; 1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;; 1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;; 1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;; 1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;; 1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;; 1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;; 1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;; 1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;; 1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;; 1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;; 1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;; 1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;; 1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;; 1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;; 1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;; 1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;; 1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;; 1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;; 1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;; 1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;; 1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;; 1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;; 1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;; 1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;; 1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;; 1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;; 1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;; 1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;; 1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;; 1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;; 1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;; 1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;; 1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;; 1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;; 1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;; 1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;; 1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;; 1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;; 1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;; 1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;; 1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;; 1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;; 1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;; 1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;; 1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;; 1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;; 1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;; 1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;; 1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;; 1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;; 1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;; 1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;; 1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;; 1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;; 1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;; 1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;; 1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;; 1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;; 1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;; 1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;; 1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;; 1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;; 1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;; 1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;; 1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;; 1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;; 1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;; 1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;; 1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;; 1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;; 1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;; 1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;; 1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;; 1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;; 1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;; 1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;; 1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;; 1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;; 1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;; 1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;; 1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;; 1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;; 1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;; 1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;; 1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;; 1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;; 1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;; 1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;; 1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;; 1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;; 1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;; 1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;; 1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;; 1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;; 1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;; 1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;; 1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;; 1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;; 1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;; 1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;; 1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;; 1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;; 1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;; 1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;; 1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;; 1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;; 1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;; 1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;; 1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;; 1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;; 1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;; 1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;; 1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;; 1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;; 1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;; 1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;; 1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L; 0041;;;;N;;;;; 1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L; 0042;;;;N;;;;; 1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L; 0043;;;;N;;;;; 1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L; 0044;;;;N;;;;; 1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L; 0045;;;;N;;;;; 1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L; 0046;;;;N;;;;; 1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L; 0047;;;;N;;;;; 1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L; 0048;;;;N;;;;; 1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L; 0049;;;;N;;;;; 1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L; 004A;;;;N;;;;; 1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L; 004B;;;;N;;;;; 1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L; 004C;;;;N;;;;; 1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L; 004D;;;;N;;;;; 1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L; 004E;;;;N;;;;; 1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L; 004F;;;;N;;;;; 1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L; 0050;;;;N;;;;; 1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; 1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L; 0052;;;;N;;;;; 1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L; 0053;;;;N;;;;; 1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L; 0054;;;;N;;;;; 1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L; 0055;;;;N;;;;; 1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L; 0056;;;;N;;;;; 1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L; 0057;;;;N;;;;; 1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L; 0058;;;;N;;;;; 1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; 1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; 1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L; 0061;;;;N;;;;; 1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L; 0062;;;;N;;;;; 1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L; 0063;;;;N;;;;; 1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L; 0064;;;;N;;;;; 1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L; 0065;;;;N;;;;; 1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L; 0066;;;;N;;;;; 1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L; 0067;;;;N;;;;; 1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L; 0068;;;;N;;;;; 1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L; 0069;;;;N;;;;; 1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L; 006A;;;;N;;;;; 1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L; 006B;;;;N;;;;; 1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L; 006C;;;;N;;;;; 1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L; 006D;;;;N;;;;; 1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L; 006E;;;;N;;;;; 1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L; 006F;;;;N;;;;; 1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L; 0070;;;;N;;;;; 1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L; 0071;;;;N;;;;; 1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L; 0072;;;;N;;;;; 1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L; 0073;;;;N;;;;; 1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L; 0074;;;;N;;;;; 1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L; 0075;;;;N;;;;; 1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L; 0076;;;;N;;;;; 1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L; 0077;;;;N;;;;; 1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L; 0078;;;;N;;;;; 1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L; 0079;;;;N;;;;; 1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L; 007A;;;;N;;;;; 1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L; 0131;;;;N;;;;; 1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L; 0237;;;;N;;;;; 1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L; 2207;;;;N;;;;; 1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; 1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; 1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; 1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; 1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; 1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; 1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; 1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; 1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; 1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; 1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; 1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; 1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; 1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; 1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; 1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; 1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; 1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; 1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; 1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; 1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; 1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; 1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; 1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; 1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; 1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L; 2207;;;;N;;;;; 1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; 1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; 1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; 1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; 1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; 1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; 1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; 1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; 1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; 1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; 1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; 1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; 1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; 1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; 1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; 1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; 1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; 1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; 1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; 1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; 1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; 1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; 1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; 1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; 1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; 1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; 1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; 1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; 1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; 1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; 1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; 1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; 1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L; 03DC;;;;N;;;;; 1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L; 03DD;;;;N;;;;; 1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; 1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; 1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; 1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; 1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; 1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; 1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; 1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; 1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; 1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; 1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; 1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; 1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; 1E803;MENDE KIKAKUI SYLLABLE M065 KEE;Lo;0;R;;;;;N;;;;; 1E804;MENDE KIKAKUI SYLLABLE M095 KE;Lo;0;R;;;;;N;;;;; 1E805;MENDE KIKAKUI SYLLABLE M076 KOO;Lo;0;R;;;;;N;;;;; 1E806;MENDE KIKAKUI SYLLABLE M048 KO;Lo;0;R;;;;;N;;;;; 1E807;MENDE KIKAKUI SYLLABLE M179 KUA;Lo;0;R;;;;;N;;;;; 1E808;MENDE KIKAKUI SYLLABLE M004 WI;Lo;0;R;;;;;N;;;;; 1E809;MENDE KIKAKUI SYLLABLE M005 WA;Lo;0;R;;;;;N;;;;; 1E80A;MENDE KIKAKUI SYLLABLE M006 WU;Lo;0;R;;;;;N;;;;; 1E80B;MENDE KIKAKUI SYLLABLE M126 WEE;Lo;0;R;;;;;N;;;;; 1E80C;MENDE KIKAKUI SYLLABLE M118 WE;Lo;0;R;;;;;N;;;;; 1E80D;MENDE KIKAKUI SYLLABLE M114 WOO;Lo;0;R;;;;;N;;;;; 1E80E;MENDE KIKAKUI SYLLABLE M045 WO;Lo;0;R;;;;;N;;;;; 1E80F;MENDE KIKAKUI SYLLABLE M194 WUI;Lo;0;R;;;;;N;;;;; 1E810;MENDE KIKAKUI SYLLABLE M143 WEI;Lo;0;R;;;;;N;;;;; 1E811;MENDE KIKAKUI SYLLABLE M061 WVI;Lo;0;R;;;;;N;;;;; 1E812;MENDE KIKAKUI SYLLABLE M049 WVA;Lo;0;R;;;;;N;;;;; 1E813;MENDE KIKAKUI SYLLABLE M139 WVE;Lo;0;R;;;;;N;;;;; 1E814;MENDE KIKAKUI SYLLABLE M007 MIN;Lo;0;R;;;;;N;;;;; 1E815;MENDE KIKAKUI SYLLABLE M008 MAN;Lo;0;R;;;;;N;;;;; 1E816;MENDE KIKAKUI SYLLABLE M009 MUN;Lo;0;R;;;;;N;;;;; 1E817;MENDE KIKAKUI SYLLABLE M059 MEN;Lo;0;R;;;;;N;;;;; 1E818;MENDE KIKAKUI SYLLABLE M094 MON;Lo;0;R;;;;;N;;;;; 1E819;MENDE KIKAKUI SYLLABLE M154 MUAN;Lo;0;R;;;;;N;;;;; 1E81A;MENDE KIKAKUI SYLLABLE M189 MUEN;Lo;0;R;;;;;N;;;;; 1E81B;MENDE KIKAKUI SYLLABLE M010 BI;Lo;0;R;;;;;N;;;;; 1E81C;MENDE KIKAKUI SYLLABLE M011 BA;Lo;0;R;;;;;N;;;;; 1E81D;MENDE KIKAKUI SYLLABLE M012 BU;Lo;0;R;;;;;N;;;;; 1E81E;MENDE KIKAKUI SYLLABLE M150 BEE;Lo;0;R;;;;;N;;;;; 1E81F;MENDE KIKAKUI SYLLABLE M097 BE;Lo;0;R;;;;;N;;;;; 1E820;MENDE KIKAKUI SYLLABLE M103 BOO;Lo;0;R;;;;;N;;;;; 1E821;MENDE KIKAKUI SYLLABLE M138 BO;Lo;0;R;;;;;N;;;;; 1E822;MENDE KIKAKUI SYLLABLE M013 I;Lo;0;R;;;;;N;;;;; 1E823;MENDE KIKAKUI SYLLABLE M014 A;Lo;0;R;;;;;N;;;;; 1E824;MENDE KIKAKUI SYLLABLE M015 U;Lo;0;R;;;;;N;;;;; 1E825;MENDE KIKAKUI SYLLABLE M163 EE;Lo;0;R;;;;;N;;;;; 1E826;MENDE KIKAKUI SYLLABLE M100 E;Lo;0;R;;;;;N;;;;; 1E827;MENDE KIKAKUI SYLLABLE M165 OO;Lo;0;R;;;;;N;;;;; 1E828;MENDE KIKAKUI SYLLABLE M147 O;Lo;0;R;;;;;N;;;;; 1E829;MENDE KIKAKUI SYLLABLE M137 EI;Lo;0;R;;;;;N;;;;; 1E82A;MENDE KIKAKUI SYLLABLE M131 IN;Lo;0;R;;;;;N;;;;; 1E82B;MENDE KIKAKUI SYLLABLE M135 IN;Lo;0;R;;;;;N;;;;; 1E82C;MENDE KIKAKUI SYLLABLE M195 AN;Lo;0;R;;;;;N;;;;; 1E82D;MENDE KIKAKUI SYLLABLE M178 EN;Lo;0;R;;;;;N;;;;; 1E82E;MENDE KIKAKUI SYLLABLE M019 SI;Lo;0;R;;;;;N;;;;; 1E82F;MENDE KIKAKUI SYLLABLE M020 SA;Lo;0;R;;;;;N;;;;; 1E830;MENDE KIKAKUI SYLLABLE M021 SU;Lo;0;R;;;;;N;;;;; 1E831;MENDE KIKAKUI SYLLABLE M162 SEE;Lo;0;R;;;;;N;;;;; 1E832;MENDE KIKAKUI SYLLABLE M116 SE;Lo;0;R;;;;;N;;;;; 1E833;MENDE KIKAKUI SYLLABLE M136 SOO;Lo;0;R;;;;;N;;;;; 1E834;MENDE KIKAKUI SYLLABLE M079 SO;Lo;0;R;;;;;N;;;;; 1E835;MENDE KIKAKUI SYLLABLE M196 SIA;Lo;0;R;;;;;N;;;;; 1E836;MENDE KIKAKUI SYLLABLE M025 LI;Lo;0;R;;;;;N;;;;; 1E837;MENDE KIKAKUI SYLLABLE M026 LA;Lo;0;R;;;;;N;;;;; 1E838;MENDE KIKAKUI SYLLABLE M027 LU;Lo;0;R;;;;;N;;;;; 1E839;MENDE KIKAKUI SYLLABLE M084 LEE;Lo;0;R;;;;;N;;;;; 1E83A;MENDE KIKAKUI SYLLABLE M073 LE;Lo;0;R;;;;;N;;;;; 1E83B;MENDE KIKAKUI SYLLABLE M054 LOO;Lo;0;R;;;;;N;;;;; 1E83C;MENDE KIKAKUI SYLLABLE M153 LO;Lo;0;R;;;;;N;;;;; 1E83D;MENDE KIKAKUI SYLLABLE M110 LONG LE;Lo;0;R;;;;;N;;;;; 1E83E;MENDE KIKAKUI SYLLABLE M016 DI;Lo;0;R;;;;;N;;;;; 1E83F;MENDE KIKAKUI SYLLABLE M017 DA;Lo;0;R;;;;;N;;;;; 1E840;MENDE KIKAKUI SYLLABLE M018 DU;Lo;0;R;;;;;N;;;;; 1E841;MENDE KIKAKUI SYLLABLE M089 DEE;Lo;0;R;;;;;N;;;;; 1E842;MENDE KIKAKUI SYLLABLE M180 DOO;Lo;0;R;;;;;N;;;;; 1E843;MENDE KIKAKUI SYLLABLE M181 DO;Lo;0;R;;;;;N;;;;; 1E844;MENDE KIKAKUI SYLLABLE M022 TI;Lo;0;R;;;;;N;;;;; 1E845;MENDE KIKAKUI SYLLABLE M023 TA;Lo;0;R;;;;;N;;;;; 1E846;MENDE KIKAKUI SYLLABLE M024 TU;Lo;0;R;;;;;N;;;;; 1E847;MENDE KIKAKUI SYLLABLE M091 TEE;Lo;0;R;;;;;N;;;;; 1E848;MENDE KIKAKUI SYLLABLE M055 TE;Lo;0;R;;;;;N;;;;; 1E849;MENDE KIKAKUI SYLLABLE M104 TOO;Lo;0;R;;;;;N;;;;; 1E84A;MENDE KIKAKUI SYLLABLE M069 TO;Lo;0;R;;;;;N;;;;; 1E84B;MENDE KIKAKUI SYLLABLE M028 JI;Lo;0;R;;;;;N;;;;; 1E84C;MENDE KIKAKUI SYLLABLE M029 JA;Lo;0;R;;;;;N;;;;; 1E84D;MENDE KIKAKUI SYLLABLE M030 JU;Lo;0;R;;;;;N;;;;; 1E84E;MENDE KIKAKUI SYLLABLE M157 JEE;Lo;0;R;;;;;N;;;;; 1E84F;MENDE KIKAKUI SYLLABLE M113 JE;Lo;0;R;;;;;N;;;;; 1E850;MENDE KIKAKUI SYLLABLE M160 JOO;Lo;0;R;;;;;N;;;;; 1E851;MENDE KIKAKUI SYLLABLE M063 JO;Lo;0;R;;;;;N;;;;; 1E852;MENDE KIKAKUI SYLLABLE M175 LONG JO;Lo;0;R;;;;;N;;;;; 1E853;MENDE KIKAKUI SYLLABLE M031 YI;Lo;0;R;;;;;N;;;;; 1E854;MENDE KIKAKUI SYLLABLE M032 YA;Lo;0;R;;;;;N;;;;; 1E855;MENDE KIKAKUI SYLLABLE M033 YU;Lo;0;R;;;;;N;;;;; 1E856;MENDE KIKAKUI SYLLABLE M109 YEE;Lo;0;R;;;;;N;;;;; 1E857;MENDE KIKAKUI SYLLABLE M080 YE;Lo;0;R;;;;;N;;;;; 1E858;MENDE KIKAKUI SYLLABLE M141 YOO;Lo;0;R;;;;;N;;;;; 1E859;MENDE KIKAKUI SYLLABLE M121 YO;Lo;0;R;;;;;N;;;;; 1E85A;MENDE KIKAKUI SYLLABLE M034 FI;Lo;0;R;;;;;N;;;;; 1E85B;MENDE KIKAKUI SYLLABLE M035 FA;Lo;0;R;;;;;N;;;;; 1E85C;MENDE KIKAKUI SYLLABLE M036 FU;Lo;0;R;;;;;N;;;;; 1E85D;MENDE KIKAKUI SYLLABLE M078 FEE;Lo;0;R;;;;;N;;;;; 1E85E;MENDE KIKAKUI SYLLABLE M075 FE;Lo;0;R;;;;;N;;;;; 1E85F;MENDE KIKAKUI SYLLABLE M133 FOO;Lo;0;R;;;;;N;;;;; 1E860;MENDE KIKAKUI SYLLABLE M088 FO;Lo;0;R;;;;;N;;;;; 1E861;MENDE KIKAKUI SYLLABLE M197 FUA;Lo;0;R;;;;;N;;;;; 1E862;MENDE KIKAKUI SYLLABLE M101 FAN;Lo;0;R;;;;;N;;;;; 1E863;MENDE KIKAKUI SYLLABLE M037 NIN;Lo;0;R;;;;;N;;;;; 1E864;MENDE KIKAKUI SYLLABLE M038 NAN;Lo;0;R;;;;;N;;;;; 1E865;MENDE KIKAKUI SYLLABLE M039 NUN;Lo;0;R;;;;;N;;;;; 1E866;MENDE KIKAKUI SYLLABLE M117 NEN;Lo;0;R;;;;;N;;;;; 1E867;MENDE KIKAKUI SYLLABLE M169 NON;Lo;0;R;;;;;N;;;;; 1E868;MENDE KIKAKUI SYLLABLE M176 HI;Lo;0;R;;;;;N;;;;; 1E869;MENDE KIKAKUI SYLLABLE M041 HA;Lo;0;R;;;;;N;;;;; 1E86A;MENDE KIKAKUI SYLLABLE M186 HU;Lo;0;R;;;;;N;;;;; 1E86B;MENDE KIKAKUI SYLLABLE M040 HEE;Lo;0;R;;;;;N;;;;; 1E86C;MENDE KIKAKUI SYLLABLE M096 HE;Lo;0;R;;;;;N;;;;; 1E86D;MENDE KIKAKUI SYLLABLE M042 HOO;Lo;0;R;;;;;N;;;;; 1E86E;MENDE KIKAKUI SYLLABLE M140 HO;Lo;0;R;;;;;N;;;;; 1E86F;MENDE KIKAKUI SYLLABLE M083 HEEI;Lo;0;R;;;;;N;;;;; 1E870;MENDE KIKAKUI SYLLABLE M128 HOOU;Lo;0;R;;;;;N;;;;; 1E871;MENDE KIKAKUI SYLLABLE M053 HIN;Lo;0;R;;;;;N;;;;; 1E872;MENDE KIKAKUI SYLLABLE M130 HAN;Lo;0;R;;;;;N;;;;; 1E873;MENDE KIKAKUI SYLLABLE M087 HUN;Lo;0;R;;;;;N;;;;; 1E874;MENDE KIKAKUI SYLLABLE M052 HEN;Lo;0;R;;;;;N;;;;; 1E875;MENDE KIKAKUI SYLLABLE M193 HON;Lo;0;R;;;;;N;;;;; 1E876;MENDE KIKAKUI SYLLABLE M046 HUAN;Lo;0;R;;;;;N;;;;; 1E877;MENDE KIKAKUI SYLLABLE M090 NGGI;Lo;0;R;;;;;N;;;;; 1E878;MENDE KIKAKUI SYLLABLE M043 NGGA;Lo;0;R;;;;;N;;;;; 1E879;MENDE KIKAKUI SYLLABLE M082 NGGU;Lo;0;R;;;;;N;;;;; 1E87A;MENDE KIKAKUI SYLLABLE M115 NGGEE;Lo;0;R;;;;;N;;;;; 1E87B;MENDE KIKAKUI SYLLABLE M146 NGGE;Lo;0;R;;;;;N;;;;; 1E87C;MENDE KIKAKUI SYLLABLE M156 NGGOO;Lo;0;R;;;;;N;;;;; 1E87D;MENDE KIKAKUI SYLLABLE M120 NGGO;Lo;0;R;;;;;N;;;;; 1E87E;MENDE KIKAKUI SYLLABLE M159 NGGAA;Lo;0;R;;;;;N;;;;; 1E87F;MENDE KIKAKUI SYLLABLE M127 NGGUA;Lo;0;R;;;;;N;;;;; 1E880;MENDE KIKAKUI SYLLABLE M086 LONG NGGE;Lo;0;R;;;;;N;;;;; 1E881;MENDE KIKAKUI SYLLABLE M106 LONG NGGOO;Lo;0;R;;;;;N;;;;; 1E882;MENDE KIKAKUI SYLLABLE M183 LONG NGGO;Lo;0;R;;;;;N;;;;; 1E883;MENDE KIKAKUI SYLLABLE M155 GI;Lo;0;R;;;;;N;;;;; 1E884;MENDE KIKAKUI SYLLABLE M111 GA;Lo;0;R;;;;;N;;;;; 1E885;MENDE KIKAKUI SYLLABLE M168 GU;Lo;0;R;;;;;N;;;;; 1E886;MENDE KIKAKUI SYLLABLE M190 GEE;Lo;0;R;;;;;N;;;;; 1E887;MENDE KIKAKUI SYLLABLE M166 GUEI;Lo;0;R;;;;;N;;;;; 1E888;MENDE KIKAKUI SYLLABLE M167 GUAN;Lo;0;R;;;;;N;;;;; 1E889;MENDE KIKAKUI SYLLABLE M184 NGEN;Lo;0;R;;;;;N;;;;; 1E88A;MENDE KIKAKUI SYLLABLE M057 NGON;Lo;0;R;;;;;N;;;;; 1E88B;MENDE KIKAKUI SYLLABLE M177 NGUAN;Lo;0;R;;;;;N;;;;; 1E88C;MENDE KIKAKUI SYLLABLE M068 PI;Lo;0;R;;;;;N;;;;; 1E88D;MENDE KIKAKUI SYLLABLE M099 PA;Lo;0;R;;;;;N;;;;; 1E88E;MENDE KIKAKUI SYLLABLE M050 PU;Lo;0;R;;;;;N;;;;; 1E88F;MENDE KIKAKUI SYLLABLE M081 PEE;Lo;0;R;;;;;N;;;;; 1E890;MENDE KIKAKUI SYLLABLE M051 PE;Lo;0;R;;;;;N;;;;; 1E891;MENDE KIKAKUI SYLLABLE M102 POO;Lo;0;R;;;;;N;;;;; 1E892;MENDE KIKAKUI SYLLABLE M066 PO;Lo;0;R;;;;;N;;;;; 1E893;MENDE KIKAKUI SYLLABLE M145 MBI;Lo;0;R;;;;;N;;;;; 1E894;MENDE KIKAKUI SYLLABLE M062 MBA;Lo;0;R;;;;;N;;;;; 1E895;MENDE KIKAKUI SYLLABLE M122 MBU;Lo;0;R;;;;;N;;;;; 1E896;MENDE KIKAKUI SYLLABLE M047 MBEE;Lo;0;R;;;;;N;;;;; 1E897;MENDE KIKAKUI SYLLABLE M188 MBEE;Lo;0;R;;;;;N;;;;; 1E898;MENDE KIKAKUI SYLLABLE M072 MBE;Lo;0;R;;;;;N;;;;; 1E899;MENDE KIKAKUI SYLLABLE M172 MBOO;Lo;0;R;;;;;N;;;;; 1E89A;MENDE KIKAKUI SYLLABLE M174 MBO;Lo;0;R;;;;;N;;;;; 1E89B;MENDE KIKAKUI SYLLABLE M187 MBUU;Lo;0;R;;;;;N;;;;; 1E89C;MENDE KIKAKUI SYLLABLE M161 LONG MBE;Lo;0;R;;;;;N;;;;; 1E89D;MENDE KIKAKUI SYLLABLE M105 LONG MBOO;Lo;0;R;;;;;N;;;;; 1E89E;MENDE KIKAKUI SYLLABLE M142 LONG MBO;Lo;0;R;;;;;N;;;;; 1E89F;MENDE KIKAKUI SYLLABLE M132 KPI;Lo;0;R;;;;;N;;;;; 1E8A0;MENDE KIKAKUI SYLLABLE M092 KPA;Lo;0;R;;;;;N;;;;; 1E8A1;MENDE KIKAKUI SYLLABLE M074 KPU;Lo;0;R;;;;;N;;;;; 1E8A2;MENDE KIKAKUI SYLLABLE M044 KPEE;Lo;0;R;;;;;N;;;;; 1E8A3;MENDE KIKAKUI SYLLABLE M108 KPE;Lo;0;R;;;;;N;;;;; 1E8A4;MENDE KIKAKUI SYLLABLE M112 KPOO;Lo;0;R;;;;;N;;;;; 1E8A5;MENDE KIKAKUI SYLLABLE M158 KPO;Lo;0;R;;;;;N;;;;; 1E8A6;MENDE KIKAKUI SYLLABLE M124 GBI;Lo;0;R;;;;;N;;;;; 1E8A7;MENDE KIKAKUI SYLLABLE M056 GBA;Lo;0;R;;;;;N;;;;; 1E8A8;MENDE KIKAKUI SYLLABLE M148 GBU;Lo;0;R;;;;;N;;;;; 1E8A9;MENDE KIKAKUI SYLLABLE M093 GBEE;Lo;0;R;;;;;N;;;;; 1E8AA;MENDE KIKAKUI SYLLABLE M107 GBE;Lo;0;R;;;;;N;;;;; 1E8AB;MENDE KIKAKUI SYLLABLE M071 GBOO;Lo;0;R;;;;;N;;;;; 1E8AC;MENDE KIKAKUI SYLLABLE M070 GBO;Lo;0;R;;;;;N;;;;; 1E8AD;MENDE KIKAKUI SYLLABLE M171 RA;Lo;0;R;;;;;N;;;;; 1E8AE;MENDE KIKAKUI SYLLABLE M123 NDI;Lo;0;R;;;;;N;;;;; 1E8AF;MENDE KIKAKUI SYLLABLE M129 NDA;Lo;0;R;;;;;N;;;;; 1E8B0;MENDE KIKAKUI SYLLABLE M125 NDU;Lo;0;R;;;;;N;;;;; 1E8B1;MENDE KIKAKUI SYLLABLE M191 NDEE;Lo;0;R;;;;;N;;;;; 1E8B2;MENDE KIKAKUI SYLLABLE M119 NDE;Lo;0;R;;;;;N;;;;; 1E8B3;MENDE KIKAKUI SYLLABLE M067 NDOO;Lo;0;R;;;;;N;;;;; 1E8B4;MENDE KIKAKUI SYLLABLE M064 NDO;Lo;0;R;;;;;N;;;;; 1E8B5;MENDE KIKAKUI SYLLABLE M152 NJA;Lo;0;R;;;;;N;;;;; 1E8B6;MENDE KIKAKUI SYLLABLE M192 NJU;Lo;0;R;;;;;N;;;;; 1E8B7;MENDE KIKAKUI SYLLABLE M149 NJEE;Lo;0;R;;;;;N;;;;; 1E8B8;MENDE KIKAKUI SYLLABLE M134 NJOO;Lo;0;R;;;;;N;;;;; 1E8B9;MENDE KIKAKUI SYLLABLE M182 VI;Lo;0;R;;;;;N;;;;; 1E8BA;MENDE KIKAKUI SYLLABLE M185 VA;Lo;0;R;;;;;N;;;;; 1E8BB;MENDE KIKAKUI SYLLABLE M151 VU;Lo;0;R;;;;;N;;;;; 1E8BC;MENDE KIKAKUI SYLLABLE M173 VEE;Lo;0;R;;;;;N;;;;; 1E8BD;MENDE KIKAKUI SYLLABLE M085 VE;Lo;0;R;;;;;N;;;;; 1E8BE;MENDE KIKAKUI SYLLABLE M144 VOO;Lo;0;R;;;;;N;;;;; 1E8BF;MENDE KIKAKUI SYLLABLE M077 VO;Lo;0;R;;;;;N;;;;; 1E8C0;MENDE KIKAKUI SYLLABLE M164 NYIN;Lo;0;R;;;;;N;;;;; 1E8C1;MENDE KIKAKUI SYLLABLE M058 NYAN;Lo;0;R;;;;;N;;;;; 1E8C2;MENDE KIKAKUI SYLLABLE M170 NYUN;Lo;0;R;;;;;N;;;;; 1E8C3;MENDE KIKAKUI SYLLABLE M098 NYEN;Lo;0;R;;;;;N;;;;; 1E8C4;MENDE KIKAKUI SYLLABLE M060 NYON;Lo;0;R;;;;;N;;;;; 1E8C7;MENDE KIKAKUI DIGIT ONE;No;0;R;;;;1;N;;;;; 1E8C8;MENDE KIKAKUI DIGIT TWO;No;0;R;;;;2;N;;;;; 1E8C9;MENDE KIKAKUI DIGIT THREE;No;0;R;;;;3;N;;;;; 1E8CA;MENDE KIKAKUI DIGIT FOUR;No;0;R;;;;4;N;;;;; 1E8CB;MENDE KIKAKUI DIGIT FIVE;No;0;R;;;;5;N;;;;; 1E8CC;MENDE KIKAKUI DIGIT SIX;No;0;R;;;;6;N;;;;; 1E8CD;MENDE KIKAKUI DIGIT SEVEN;No;0;R;;;;7;N;;;;; 1E8CE;MENDE KIKAKUI DIGIT EIGHT;No;0;R;;;;8;N;;;;; 1E8CF;MENDE KIKAKUI DIGIT NINE;No;0;R;;;;9;N;;;;; 1E8D0;MENDE KIKAKUI COMBINING NUMBER TEENS;Mn;220;NSM;;;;;N;;;;; 1E8D1;MENDE KIKAKUI COMBINING NUMBER TENS;Mn;220;NSM;;;;;N;;;;; 1E8D2;MENDE KIKAKUI COMBINING NUMBER HUNDREDS;Mn;220;NSM;;;;;N;;;;; 1E8D3;MENDE KIKAKUI COMBINING NUMBER THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D4;MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D5;MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D6;MENDE KIKAKUI COMBINING NUMBER MILLIONS;Mn;220;NSM;;;;;N;;;;; 1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL; 0627;;;;N;;;;; 1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL; 0628;;;;N;;;;; 1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EE03;ARABIC MATHEMATICAL DAL;Lo;0;AL; 062F;;;;N;;;;; 1EE05;ARABIC MATHEMATICAL WAW;Lo;0;AL; 0648;;;;N;;;;; 1EE06;ARABIC MATHEMATICAL ZAIN;Lo;0;AL; 0632;;;;N;;;;; 1EE07;ARABIC MATHEMATICAL HAH;Lo;0;AL; 062D;;;;N;;;;; 1EE08;ARABIC MATHEMATICAL TAH;Lo;0;AL; 0637;;;;N;;;;; 1EE09;ARABIC MATHEMATICAL YEH;Lo;0;AL; 064A;;;;N;;;;; 1EE0A;ARABIC MATHEMATICAL KAF;Lo;0;AL; 0643;;;;N;;;;; 1EE0B;ARABIC MATHEMATICAL LAM;Lo;0;AL; 0644;;;;N;;;;; 1EE0C;ARABIC MATHEMATICAL MEEM;Lo;0;AL; 0645;;;;N;;;;; 1EE0D;ARABIC MATHEMATICAL NOON;Lo;0;AL; 0646;;;;N;;;;; 1EE0E;ARABIC MATHEMATICAL SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EE0F;ARABIC MATHEMATICAL AIN;Lo;0;AL; 0639;;;;N;;;;; 1EE10;ARABIC MATHEMATICAL FEH;Lo;0;AL; 0641;;;;N;;;;; 1EE11;ARABIC MATHEMATICAL SAD;Lo;0;AL; 0635;;;;N;;;;; 1EE12;ARABIC MATHEMATICAL QAF;Lo;0;AL; 0642;;;;N;;;;; 1EE13;ARABIC MATHEMATICAL REH;Lo;0;AL; 0631;;;;N;;;;; 1EE14;ARABIC MATHEMATICAL SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EE15;ARABIC MATHEMATICAL TEH;Lo;0;AL; 062A;;;;N;;;;; 1EE16;ARABIC MATHEMATICAL THEH;Lo;0;AL; 062B;;;;N;;;;; 1EE17;ARABIC MATHEMATICAL KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EE18;ARABIC MATHEMATICAL THAL;Lo;0;AL; 0630;;;;N;;;;; 1EE19;ARABIC MATHEMATICAL DAD;Lo;0;AL; 0636;;;;N;;;;; 1EE1A;ARABIC MATHEMATICAL ZAH;Lo;0;AL; 0638;;;;N;;;;; 1EE1B;ARABIC MATHEMATICAL GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EE1C;ARABIC MATHEMATICAL DOTLESS BEH;Lo;0;AL; 066E;;;;N;;;;; 1EE1D;ARABIC MATHEMATICAL DOTLESS NOON;Lo;0;AL; 06BA;;;;N;;;;; 1EE1E;ARABIC MATHEMATICAL DOTLESS FEH;Lo;0;AL; 06A1;;;;N;;;;; 1EE1F;ARABIC MATHEMATICAL DOTLESS QAF;Lo;0;AL; 066F;;;;N;;;;; 1EE21;ARABIC MATHEMATICAL INITIAL BEH;Lo;0;AL; 0628;;;;N;;;;; 1EE22;ARABIC MATHEMATICAL INITIAL JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EE24;ARABIC MATHEMATICAL INITIAL HEH;Lo;0;AL; 0647;;;;N;;;;; 1EE27;ARABIC MATHEMATICAL INITIAL HAH;Lo;0;AL; 062D;;;;N;;;;; 1EE29;ARABIC MATHEMATICAL INITIAL YEH;Lo;0;AL; 064A;;;;N;;;;; 1EE2A;ARABIC MATHEMATICAL INITIAL KAF;Lo;0;AL; 0643;;;;N;;;;; 1EE2B;ARABIC MATHEMATICAL INITIAL LAM;Lo;0;AL; 0644;;;;N;;;;; 1EE2C;ARABIC MATHEMATICAL INITIAL MEEM;Lo;0;AL; 0645;;;;N;;;;; 1EE2D;ARABIC MATHEMATICAL INITIAL NOON;Lo;0;AL; 0646;;;;N;;;;; 1EE2E;ARABIC MATHEMATICAL INITIAL SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EE2F;ARABIC MATHEMATICAL INITIAL AIN;Lo;0;AL; 0639;;;;N;;;;; 1EE30;ARABIC MATHEMATICAL INITIAL FEH;Lo;0;AL; 0641;;;;N;;;;; 1EE31;ARABIC MATHEMATICAL INITIAL SAD;Lo;0;AL; 0635;;;;N;;;;; 1EE32;ARABIC MATHEMATICAL INITIAL QAF;Lo;0;AL; 0642;;;;N;;;;; 1EE34;ARABIC MATHEMATICAL INITIAL SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EE35;ARABIC MATHEMATICAL INITIAL TEH;Lo;0;AL; 062A;;;;N;;;;; 1EE36;ARABIC MATHEMATICAL INITIAL THEH;Lo;0;AL; 062B;;;;N;;;;; 1EE37;ARABIC MATHEMATICAL INITIAL KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EE39;ARABIC MATHEMATICAL INITIAL DAD;Lo;0;AL; 0636;;;;N;;;;; 1EE3B;ARABIC MATHEMATICAL INITIAL GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EE42;ARABIC MATHEMATICAL TAILED JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EE47;ARABIC MATHEMATICAL TAILED HAH;Lo;0;AL; 062D;;;;N;;;;; 1EE49;ARABIC MATHEMATICAL TAILED YEH;Lo;0;AL; 064A;;;;N;;;;; 1EE4B;ARABIC MATHEMATICAL TAILED LAM;Lo;0;AL; 0644;;;;N;;;;; 1EE4D;ARABIC MATHEMATICAL TAILED NOON;Lo;0;AL; 0646;;;;N;;;;; 1EE4E;ARABIC MATHEMATICAL TAILED SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EE4F;ARABIC MATHEMATICAL TAILED AIN;Lo;0;AL; 0639;;;;N;;;;; 1EE51;ARABIC MATHEMATICAL TAILED SAD;Lo;0;AL; 0635;;;;N;;;;; 1EE52;ARABIC MATHEMATICAL TAILED QAF;Lo;0;AL; 0642;;;;N;;;;; 1EE54;ARABIC MATHEMATICAL TAILED SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EE57;ARABIC MATHEMATICAL TAILED KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EE59;ARABIC MATHEMATICAL TAILED DAD;Lo;0;AL; 0636;;;;N;;;;; 1EE5B;ARABIC MATHEMATICAL TAILED GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EE5D;ARABIC MATHEMATICAL TAILED DOTLESS NOON;Lo;0;AL; 06BA;;;;N;;;;; 1EE5F;ARABIC MATHEMATICAL TAILED DOTLESS QAF;Lo;0;AL; 066F;;;;N;;;;; 1EE61;ARABIC MATHEMATICAL STRETCHED BEH;Lo;0;AL; 0628;;;;N;;;;; 1EE62;ARABIC MATHEMATICAL STRETCHED JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EE64;ARABIC MATHEMATICAL STRETCHED HEH;Lo;0;AL; 0647;;;;N;;;;; 1EE67;ARABIC MATHEMATICAL STRETCHED HAH;Lo;0;AL; 062D;;;;N;;;;; 1EE68;ARABIC MATHEMATICAL STRETCHED TAH;Lo;0;AL; 0637;;;;N;;;;; 1EE69;ARABIC MATHEMATICAL STRETCHED YEH;Lo;0;AL; 064A;;;;N;;;;; 1EE6A;ARABIC MATHEMATICAL STRETCHED KAF;Lo;0;AL; 0643;;;;N;;;;; 1EE6C;ARABIC MATHEMATICAL STRETCHED MEEM;Lo;0;AL; 0645;;;;N;;;;; 1EE6D;ARABIC MATHEMATICAL STRETCHED NOON;Lo;0;AL; 0646;;;;N;;;;; 1EE6E;ARABIC MATHEMATICAL STRETCHED SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EE6F;ARABIC MATHEMATICAL STRETCHED AIN;Lo;0;AL; 0639;;;;N;;;;; 1EE70;ARABIC MATHEMATICAL STRETCHED FEH;Lo;0;AL; 0641;;;;N;;;;; 1EE71;ARABIC MATHEMATICAL STRETCHED SAD;Lo;0;AL; 0635;;;;N;;;;; 1EE72;ARABIC MATHEMATICAL STRETCHED QAF;Lo;0;AL; 0642;;;;N;;;;; 1EE74;ARABIC MATHEMATICAL STRETCHED SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EE75;ARABIC MATHEMATICAL STRETCHED TEH;Lo;0;AL; 062A;;;;N;;;;; 1EE76;ARABIC MATHEMATICAL STRETCHED THEH;Lo;0;AL; 062B;;;;N;;;;; 1EE77;ARABIC MATHEMATICAL STRETCHED KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EE79;ARABIC MATHEMATICAL STRETCHED DAD;Lo;0;AL; 0636;;;;N;;;;; 1EE7A;ARABIC MATHEMATICAL STRETCHED ZAH;Lo;0;AL; 0638;;;;N;;;;; 1EE7B;ARABIC MATHEMATICAL STRETCHED GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EE7C;ARABIC MATHEMATICAL STRETCHED DOTLESS BEH;Lo;0;AL; 066E;;;;N;;;;; 1EE7E;ARABIC MATHEMATICAL STRETCHED DOTLESS FEH;Lo;0;AL; 06A1;;;;N;;;;; 1EE80;ARABIC MATHEMATICAL LOOPED ALEF;Lo;0;AL; 0627;;;;N;;;;; 1EE81;ARABIC MATHEMATICAL LOOPED BEH;Lo;0;AL; 0628;;;;N;;;;; 1EE82;ARABIC MATHEMATICAL LOOPED JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EE83;ARABIC MATHEMATICAL LOOPED DAL;Lo;0;AL; 062F;;;;N;;;;; 1EE84;ARABIC MATHEMATICAL LOOPED HEH;Lo;0;AL; 0647;;;;N;;;;; 1EE85;ARABIC MATHEMATICAL LOOPED WAW;Lo;0;AL; 0648;;;;N;;;;; 1EE86;ARABIC MATHEMATICAL LOOPED ZAIN;Lo;0;AL; 0632;;;;N;;;;; 1EE87;ARABIC MATHEMATICAL LOOPED HAH;Lo;0;AL; 062D;;;;N;;;;; 1EE88;ARABIC MATHEMATICAL LOOPED TAH;Lo;0;AL; 0637;;;;N;;;;; 1EE89;ARABIC MATHEMATICAL LOOPED YEH;Lo;0;AL; 064A;;;;N;;;;; 1EE8B;ARABIC MATHEMATICAL LOOPED LAM;Lo;0;AL; 0644;;;;N;;;;; 1EE8C;ARABIC MATHEMATICAL LOOPED MEEM;Lo;0;AL; 0645;;;;N;;;;; 1EE8D;ARABIC MATHEMATICAL LOOPED NOON;Lo;0;AL; 0646;;;;N;;;;; 1EE8E;ARABIC MATHEMATICAL LOOPED SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EE8F;ARABIC MATHEMATICAL LOOPED AIN;Lo;0;AL; 0639;;;;N;;;;; 1EE90;ARABIC MATHEMATICAL LOOPED FEH;Lo;0;AL; 0641;;;;N;;;;; 1EE91;ARABIC MATHEMATICAL LOOPED SAD;Lo;0;AL; 0635;;;;N;;;;; 1EE92;ARABIC MATHEMATICAL LOOPED QAF;Lo;0;AL; 0642;;;;N;;;;; 1EE93;ARABIC MATHEMATICAL LOOPED REH;Lo;0;AL; 0631;;;;N;;;;; 1EE94;ARABIC MATHEMATICAL LOOPED SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EE95;ARABIC MATHEMATICAL LOOPED TEH;Lo;0;AL; 062A;;;;N;;;;; 1EE96;ARABIC MATHEMATICAL LOOPED THEH;Lo;0;AL; 062B;;;;N;;;;; 1EE97;ARABIC MATHEMATICAL LOOPED KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EE98;ARABIC MATHEMATICAL LOOPED THAL;Lo;0;AL; 0630;;;;N;;;;; 1EE99;ARABIC MATHEMATICAL LOOPED DAD;Lo;0;AL; 0636;;;;N;;;;; 1EE9A;ARABIC MATHEMATICAL LOOPED ZAH;Lo;0;AL; 0638;;;;N;;;;; 1EE9B;ARABIC MATHEMATICAL LOOPED GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EEA1;ARABIC MATHEMATICAL DOUBLE-STRUCK BEH;Lo;0;AL; 0628;;;;N;;;;; 1EEA2;ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM;Lo;0;AL; 062C;;;;N;;;;; 1EEA3;ARABIC MATHEMATICAL DOUBLE-STRUCK DAL;Lo;0;AL; 062F;;;;N;;;;; 1EEA5;ARABIC MATHEMATICAL DOUBLE-STRUCK WAW;Lo;0;AL; 0648;;;;N;;;;; 1EEA6;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN;Lo;0;AL; 0632;;;;N;;;;; 1EEA7;ARABIC MATHEMATICAL DOUBLE-STRUCK HAH;Lo;0;AL; 062D;;;;N;;;;; 1EEA8;ARABIC MATHEMATICAL DOUBLE-STRUCK TAH;Lo;0;AL; 0637;;;;N;;;;; 1EEA9;ARABIC MATHEMATICAL DOUBLE-STRUCK YEH;Lo;0;AL; 064A;;;;N;;;;; 1EEAB;ARABIC MATHEMATICAL DOUBLE-STRUCK LAM;Lo;0;AL; 0644;;;;N;;;;; 1EEAC;ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM;Lo;0;AL; 0645;;;;N;;;;; 1EEAD;ARABIC MATHEMATICAL DOUBLE-STRUCK NOON;Lo;0;AL; 0646;;;;N;;;;; 1EEAE;ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN;Lo;0;AL; 0633;;;;N;;;;; 1EEAF;ARABIC MATHEMATICAL DOUBLE-STRUCK AIN;Lo;0;AL; 0639;;;;N;;;;; 1EEB0;ARABIC MATHEMATICAL DOUBLE-STRUCK FEH;Lo;0;AL; 0641;;;;N;;;;; 1EEB1;ARABIC MATHEMATICAL DOUBLE-STRUCK SAD;Lo;0;AL; 0635;;;;N;;;;; 1EEB2;ARABIC MATHEMATICAL DOUBLE-STRUCK QAF;Lo;0;AL; 0642;;;;N;;;;; 1EEB3;ARABIC MATHEMATICAL DOUBLE-STRUCK REH;Lo;0;AL; 0631;;;;N;;;;; 1EEB4;ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN;Lo;0;AL; 0634;;;;N;;;;; 1EEB5;ARABIC MATHEMATICAL DOUBLE-STRUCK TEH;Lo;0;AL; 062A;;;;N;;;;; 1EEB6;ARABIC MATHEMATICAL DOUBLE-STRUCK THEH;Lo;0;AL; 062B;;;;N;;;;; 1EEB7;ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH;Lo;0;AL; 062E;;;;N;;;;; 1EEB8;ARABIC MATHEMATICAL DOUBLE-STRUCK THAL;Lo;0;AL; 0630;;;;N;;;;; 1EEB9;ARABIC MATHEMATICAL DOUBLE-STRUCK DAD;Lo;0;AL; 0636;;;;N;;;;; 1EEBA;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH;Lo;0;AL; 0638;;;;N;;;;; 1EEBB;ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN;Lo;0;AL; 063A;;;;N;;;;; 1EEF0;ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL;Sm;0;ON;;;;;N;;;;; 1EEF1;ARABIC MATHEMATICAL OPERATOR HAH WITH DAL;Sm;0;ON;;;;;N;;;;; 1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;; 1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;; 1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;; 1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;; 1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;; 1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;; 1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;; 1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;; 1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;; 1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;; 1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;; 1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;; 1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;; 1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;; 1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;; 1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;; 1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;; 1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;; 1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;; 1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;; 1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;; 1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;; 1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;; 1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;; 1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;; 1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;; 1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;; 1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;; 1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;; 1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;; 1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;; 1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;; 1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;; 1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;; 1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;; 1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;; 1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;; 1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;; 1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;; 1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;; 1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;; 1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;; 1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;; 1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;; 1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;; 1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;; 1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;; 1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;; 1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;; 1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;; 1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;; 1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;; 1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;; 1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;; 1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;; 1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;; 1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;; 1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;; 1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;; 1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;; 1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;; 1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;; 1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;; 1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;; 1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;; 1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;; 1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;; 1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;; 1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;; 1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;; 1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;; 1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;; 1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;; 1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;; 1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;; 1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;; 1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;; 1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;; 1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;; 1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;; 1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;; 1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;; 1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;; 1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;; 1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;; 1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;; 1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;; 1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;; 1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;; 1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;; 1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;; 1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;; 1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;; 1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;; 1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;; 1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;; 1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;; 1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;; 1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;; 1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;; 1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;; 1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;; 1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;; 1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;; 1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;; 1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;; 1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;; 1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;; 1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;; 1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;; 1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;; 1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;; 1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;; 1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;; 1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;; 1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;; 1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; 1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; 1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; 1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;; 1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;; 1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;; 1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;; 1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;; 1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;; 1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;; 1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;; 1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;; 1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BF;PLAYING CARD RED JOKER;So;0;ON;;;;;N;;;;; 1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;; 1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;; 1F0E0;PLAYING CARD FOOL;So;0;ON;;;;;N;;;;; 1F0E1;PLAYING CARD TRUMP-1;So;0;ON;;;;;N;;;;; 1F0E2;PLAYING CARD TRUMP-2;So;0;ON;;;;;N;;;;; 1F0E3;PLAYING CARD TRUMP-3;So;0;ON;;;;;N;;;;; 1F0E4;PLAYING CARD TRUMP-4;So;0;ON;;;;;N;;;;; 1F0E5;PLAYING CARD TRUMP-5;So;0;ON;;;;;N;;;;; 1F0E6;PLAYING CARD TRUMP-6;So;0;ON;;;;;N;;;;; 1F0E7;PLAYING CARD TRUMP-7;So;0;ON;;;;;N;;;;; 1F0E8;PLAYING CARD TRUMP-8;So;0;ON;;;;;N;;;;; 1F0E9;PLAYING CARD TRUMP-9;So;0;ON;;;;;N;;;;; 1F0EA;PLAYING CARD TRUMP-10;So;0;ON;;;;;N;;;;; 1F0EB;PLAYING CARD TRUMP-11;So;0;ON;;;;;N;;;;; 1F0EC;PLAYING CARD TRUMP-12;So;0;ON;;;;;N;;;;; 1F0ED;PLAYING CARD TRUMP-13;So;0;ON;;;;;N;;;;; 1F0EE;PLAYING CARD TRUMP-14;So;0;ON;;;;;N;;;;; 1F0EF;PLAYING CARD TRUMP-15;So;0;ON;;;;;N;;;;; 1F0F0;PLAYING CARD TRUMP-16;So;0;ON;;;;;N;;;;; 1F0F1;PLAYING CARD TRUMP-17;So;0;ON;;;;;N;;;;; 1F0F2;PLAYING CARD TRUMP-18;So;0;ON;;;;;N;;;;; 1F0F3;PLAYING CARD TRUMP-19;So;0;ON;;;;;N;;;;; 1F0F4;PLAYING CARD TRUMP-20;So;0;ON;;;;;N;;;;; 1F0F5;PLAYING CARD TRUMP-21;So;0;ON;;;;;N;;;;; 1F100;DIGIT ZERO FULL STOP;No;0;EN; 0030 002E;;0;0;N;;;;; 1F101;DIGIT ZERO COMMA;No;0;EN; 0030 002C;;0;0;N;;;;; 1F102;DIGIT ONE COMMA;No;0;EN; 0031 002C;;1;1;N;;;;; 1F103;DIGIT TWO COMMA;No;0;EN; 0032 002C;;2;2;N;;;;; 1F104;DIGIT THREE COMMA;No;0;EN; 0033 002C;;3;3;N;;;;; 1F105;DIGIT FOUR COMMA;No;0;EN; 0034 002C;;4;4;N;;;;; 1F106;DIGIT FIVE COMMA;No;0;EN; 0035 002C;;5;5;N;;;;; 1F107;DIGIT SIX COMMA;No;0;EN; 0036 002C;;6;6;N;;;;; 1F108;DIGIT SEVEN COMMA;No;0;EN; 0037 002C;;7;7;N;;;;; 1F109;DIGIT EIGHT COMMA;No;0;EN; 0038 002C;;8;8;N;;;;; 1F10A;DIGIT NINE COMMA;No;0;EN; 0039 002C;;9;9;N;;;;; 1F10B;DINGBAT CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; 1F10C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; 1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L; 0028 0041 0029;;;;N;;;;; 1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L; 0028 0042 0029;;;;N;;;;; 1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L; 0028 0043 0029;;;;N;;;;; 1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L; 0028 0044 0029;;;;N;;;;; 1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L; 0028 0045 0029;;;;N;;;;; 1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L; 0028 0046 0029;;;;N;;;;; 1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L; 0028 0047 0029;;;;N;;;;; 1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L; 0028 0048 0029;;;;N;;;;; 1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L; 0028 0049 0029;;;;N;;;;; 1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L; 0028 004A 0029;;;;N;;;;; 1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L; 0028 004B 0029;;;;N;;;;; 1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L; 0028 004C 0029;;;;N;;;;; 1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L; 0028 004D 0029;;;;N;;;;; 1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L; 0028 004E 0029;;;;N;;;;; 1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L; 0028 004F 0029;;;;N;;;;; 1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L; 0028 0050 0029;;;;N;;;;; 1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L; 0028 0051 0029;;;;N;;;;; 1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L; 0028 0052 0029;;;;N;;;;; 1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L; 0028 0053 0029;;;;N;;;;; 1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L; 0028 0054 0029;;;;N;;;;; 1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L; 0028 0055 0029;;;;N;;;;; 1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L; 0028 0056 0029;;;;N;;;;; 1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L; 0028 0057 0029;;;;N;;;;; 1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L; 0028 0058 0029;;;;N;;;;; 1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L; 0028 0059 0029;;;;N;;;;; 1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L; 0028 005A 0029;;;;N;;;;; 1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L; 3014 0053 3015;;;;N;;;;; 1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; 1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; 1F12D;CIRCLED CD;So;0;L; 0043 0044;;;;N;;;;; 1F12E;CIRCLED WZ;So;0;L; 0057 005A;;;;N;;;;; 1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;; 1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;; 1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; 1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;; 1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;; 1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;; 1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;; 1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;; 1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;; 1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;; 1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;; 1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;; 1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;; 1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;; 1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;; 1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;; 1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;; 1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; 1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;; 1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;; 1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;; 1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;; 1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;; 1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;; 1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;; 1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;; 1F14A;SQUARED HV;So;0;L; 0048 0056;;;;N;;;;; 1F14B;SQUARED MV;So;0;L; 004D 0056;;;;N;;;;; 1F14C;SQUARED SD;So;0;L; 0053 0044;;;;N;;;;; 1F14D;SQUARED SS;So;0;L; 0053 0053;;;;N;;;;; 1F14E;SQUARED PPV;So;0;L; 0050 0050 0056;;;;N;;;;; 1F14F;SQUARED WC;So;0;L; 0057 0043;;;;N;;;;; 1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; 1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; 1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; 1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; 1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; 1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; 1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; 1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; 1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; 1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; 1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; 1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; 1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; 1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; 1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; 1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; 1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; 1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; 1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; 1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; 1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; 1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; 1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; 1F16A;RAISED MC SIGN;So;0;ON; 004D 0043;;;;N;;;;; 1F16B;RAISED MD SIGN;So;0;ON; 004D 0044;;;;N;;;;; 1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; 1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; 1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; 1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; 1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; 1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; 1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; 1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; 1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; 1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; 1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; 1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; 1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; 1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; 1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; 1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; 1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; 1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; 1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; 1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; 1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; 1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; 1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; 1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; 1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; 1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; 1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;; 1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;; 1F190;SQUARE DJ;So;0;L; 0044 004A;;;;N;;;;; 1F191;SQUARED CL;So;0;L;;;;;N;;;;; 1F192;SQUARED COOL;So;0;L;;;;;N;;;;; 1F193;SQUARED FREE;So;0;L;;;;;N;;;;; 1F194;SQUARED ID;So;0;L;;;;;N;;;;; 1F195;SQUARED NEW;So;0;L;;;;;N;;;;; 1F196;SQUARED NG;So;0;L;;;;;N;;;;; 1F197;SQUARED OK;So;0;L;;;;;N;;;;; 1F198;SQUARED SOS;So;0;L;;;;;N;;;;; 1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; 1F19A;SQUARED VS;So;0;L;;;;;N;;;;; 1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; 1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; 1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; 1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;; 1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;; 1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;; 1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;; 1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;; 1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;; 1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;; 1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;; 1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;; 1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;; 1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;; 1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;; 1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;; 1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;; 1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;; 1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;; 1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;; 1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;; 1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;; 1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;; 1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;; 1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;; 1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;; 1F200;SQUARE HIRAGANA HOKA;So;0;L; 307B 304B;;;;N;;;;; 1F201;SQUARED KATAKANA KOKO;So;0;L; 30B3 30B3;;;;N;;;;; 1F202;SQUARED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; 1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L; 624B;;;;N;;;;; 1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L; 5B57;;;;N;;;;; 1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L; 53CC;;;;N;;;;; 1F213;SQUARED KATAKANA DE;So;0;L; 30C7;;;;N;;;;; 1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 4E8C;;;;N;;;;; 1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L; 591A;;;;N;;;;; 1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L; 89E3;;;;N;;;;; 1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L; 5929;;;;N;;;;; 1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L; 4EA4;;;;N;;;;; 1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L; 6620;;;;N;;;;; 1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L; 7121;;;;N;;;;; 1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L; 6599;;;;N;;;;; 1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L; 524D;;;;N;;;;; 1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L; 5F8C;;;;N;;;;; 1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L; 518D;;;;N;;;;; 1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L; 65B0;;;;N;;;;; 1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L; 521D;;;;N;;;;; 1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L; 7D42;;;;N;;;;; 1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L; 751F;;;;N;;;;; 1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L; 8CA9;;;;N;;;;; 1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L; 58F0;;;;N;;;;; 1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L; 5439;;;;N;;;;; 1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L; 6F14;;;;N;;;;; 1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L; 6295;;;;N;;;;; 1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L; 6355;;;;N;;;;; 1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L; 4E00;;;;N;;;;; 1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 4E09;;;;N;;;;; 1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L; 904A;;;;N;;;;; 1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L; 5DE6;;;;N;;;;; 1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L; 4E2D;;;;N;;;;; 1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L; 53F3;;;;N;;;;; 1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L; 6307;;;;N;;;;; 1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L; 8D70;;;;N;;;;; 1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 6253;;;;N;;;;; 1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L; 7981;;;;N;;;;; 1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L; 7A7A;;;;N;;;;; 1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L; 5408;;;;N;;;;; 1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L; 6E80;;;;N;;;;; 1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L; 6709;;;;N;;;;; 1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L; 6708;;;;N;;;;; 1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L; 7533;;;;N;;;;; 1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L; 5272;;;;N;;;;; 1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L; 55B6;;;;N;;;;; 1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L; 3014 672C 3015;;;;N;;;;; 1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 3014 4E09 3015;;;;N;;;;; 1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 3014 4E8C 3015;;;;N;;;;; 1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L; 3014 5B89 3015;;;;N;;;;; 1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L; 3014 70B9 3015;;;;N;;;;; 1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 3014 6253 3015;;;;N;;;;; 1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L; 3014 76D7 3015;;;;N;;;;; 1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L; 3014 52DD 3015;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L; 3014 6557 3015;;;;N;;;;; 1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L; 5F97;;;;N;;;;; 1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L; 53EF;;;;N;;;;; 1F300;CYCLONE;So;0;ON;;;;;N;;;;; 1F301;FOGGY;So;0;ON;;;;;N;;;;; 1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; 1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;; 1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;; 1F305;SUNRISE;So;0;ON;;;;;N;;;;; 1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;; 1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;; 1F308;RAINBOW;So;0;ON;;;;;N;;;;; 1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;; 1F30A;WATER WAVE;So;0;ON;;;;;N;;;;; 1F30B;VOLCANO;So;0;ON;;;;;N;;;;; 1F30C;MILKY WAY;So;0;ON;;;;;N;;;;; 1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;; 1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;; 1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;; 1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;; 1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;; 1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;; 1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;; 1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;; 1F321;THERMOMETER;So;0;ON;;;;;N;;;;; 1F322;BLACK DROPLET;So;0;ON;;;;;N;;;;; 1F323;WHITE SUN;So;0;ON;;;;;N;;;;; 1F324;WHITE SUN WITH SMALL CLOUD;So;0;ON;;;;;N;;;;; 1F325;WHITE SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; 1F326;WHITE SUN BEHIND CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; 1F327;CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; 1F328;CLOUD WITH SNOW;So;0;ON;;;;;N;;;;; 1F329;CLOUD WITH LIGHTNING;So;0;ON;;;;;N;;;;; 1F32A;CLOUD WITH TORNADO;So;0;ON;;;;;N;;;;; 1F32B;FOG;So;0;ON;;;;;N;;;;; 1F32C;WIND BLOWING FACE;So;0;ON;;;;;N;;;;; 1F330;CHESTNUT;So;0;ON;;;;;N;;;;; 1F331;SEEDLING;So;0;ON;;;;;N;;;;; 1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;; 1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;; 1F334;PALM TREE;So;0;ON;;;;;N;;;;; 1F335;CACTUS;So;0;ON;;;;;N;;;;; 1F336;HOT PEPPER;So;0;ON;;;;;N;;;;; 1F337;TULIP;So;0;ON;;;;;N;;;;; 1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;; 1F339;ROSE;So;0;ON;;;;;N;;;;; 1F33A;HIBISCUS;So;0;ON;;;;;N;;;;; 1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;; 1F33C;BLOSSOM;So;0;ON;;;;;N;;;;; 1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;; 1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;; 1F33F;HERB;So;0;ON;;;;;N;;;;; 1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;; 1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;; 1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;; 1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;; 1F344;MUSHROOM;So;0;ON;;;;;N;;;;; 1F345;TOMATO;So;0;ON;;;;;N;;;;; 1F346;AUBERGINE;So;0;ON;;;;;N;;;;; 1F347;GRAPES;So;0;ON;;;;;N;;;;; 1F348;MELON;So;0;ON;;;;;N;;;;; 1F349;WATERMELON;So;0;ON;;;;;N;;;;; 1F34A;TANGERINE;So;0;ON;;;;;N;;;;; 1F34B;LEMON;So;0;ON;;;;;N;;;;; 1F34C;BANANA;So;0;ON;;;;;N;;;;; 1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;; 1F34E;RED APPLE;So;0;ON;;;;;N;;;;; 1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;; 1F350;PEAR;So;0;ON;;;;;N;;;;; 1F351;PEACH;So;0;ON;;;;;N;;;;; 1F352;CHERRIES;So;0;ON;;;;;N;;;;; 1F353;STRAWBERRY;So;0;ON;;;;;N;;;;; 1F354;HAMBURGER;So;0;ON;;;;;N;;;;; 1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;; 1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;; 1F357;POULTRY LEG;So;0;ON;;;;;N;;;;; 1F358;RICE CRACKER;So;0;ON;;;;;N;;;;; 1F359;RICE BALL;So;0;ON;;;;;N;;;;; 1F35A;COOKED RICE;So;0;ON;;;;;N;;;;; 1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;; 1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;; 1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;; 1F35E;BREAD;So;0;ON;;;;;N;;;;; 1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;; 1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;; 1F361;DANGO;So;0;ON;;;;;N;;;;; 1F362;ODEN;So;0;ON;;;;;N;;;;; 1F363;SUSHI;So;0;ON;;;;;N;;;;; 1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;; 1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;; 1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;; 1F367;SHAVED ICE;So;0;ON;;;;;N;;;;; 1F368;ICE CREAM;So;0;ON;;;;;N;;;;; 1F369;DOUGHNUT;So;0;ON;;;;;N;;;;; 1F36A;COOKIE;So;0;ON;;;;;N;;;;; 1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;; 1F36C;CANDY;So;0;ON;;;;;N;;;;; 1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;; 1F36E;CUSTARD;So;0;ON;;;;;N;;;;; 1F36F;HONEY POT;So;0;ON;;;;;N;;;;; 1F370;SHORTCAKE;So;0;ON;;;;;N;;;;; 1F371;BENTO BOX;So;0;ON;;;;;N;;;;; 1F372;POT OF FOOD;So;0;ON;;;;;N;;;;; 1F373;COOKING;So;0;ON;;;;;N;;;;; 1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;; 1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;; 1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;; 1F377;WINE GLASS;So;0;ON;;;;;N;;;;; 1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;; 1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;; 1F37A;BEER MUG;So;0;ON;;;;;N;;;;; 1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;; 1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;; 1F37D;FORK AND KNIFE WITH PLATE;So;0;ON;;;;;N;;;;; 1F380;RIBBON;So;0;ON;;;;;N;;;;; 1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;; 1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;; 1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;; 1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;; 1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;; 1F386;FIREWORKS;So;0;ON;;;;;N;;;;; 1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;; 1F388;BALLOON;So;0;ON;;;;;N;;;;; 1F389;PARTY POPPER;So;0;ON;;;;;N;;;;; 1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;; 1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;; 1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;; 1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;; 1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;; 1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;; 1F390;WIND CHIME;So;0;ON;;;;;N;;;;; 1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;; 1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;; 1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;; 1F394;HEART WITH TIP ON THE LEFT;So;0;ON;;;;;N;;;;; 1F395;BOUQUET OF FLOWERS;So;0;ON;;;;;N;;;;; 1F396;MILITARY MEDAL;So;0;ON;;;;;N;;;;; 1F397;REMINDER RIBBON;So;0;ON;;;;;N;;;;; 1F398;MUSICAL KEYBOARD WITH JACKS;So;0;ON;;;;;N;;;;; 1F399;STUDIO MICROPHONE;So;0;ON;;;;;N;;;;; 1F39A;LEVEL SLIDER;So;0;ON;;;;;N;;;;; 1F39B;CONTROL KNOBS;So;0;ON;;;;;N;;;;; 1F39C;BEAMED ASCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F39D;BEAMED DESCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F39E;FILM FRAMES;So;0;ON;;;;;N;;;;; 1F39F;ADMISSION TICKETS;So;0;ON;;;;;N;;;;; 1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;; 1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;; 1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;; 1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;; 1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;; 1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;; 1F3A6;CINEMA;So;0;ON;;;;;N;;;;; 1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;; 1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;; 1F3A9;TOP HAT;So;0;ON;;;;;N;;;;; 1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;; 1F3AB;TICKET;So;0;ON;;;;;N;;;;; 1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;; 1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;; 1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;; 1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;; 1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;; 1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;; 1F3B2;GAME DIE;So;0;ON;;;;;N;;;;; 1F3B3;BOWLING;So;0;ON;;;;;N;;;;; 1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;; 1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;; 1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;; 1F3B8;GUITAR;So;0;ON;;;;;N;;;;; 1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;; 1F3BA;TRUMPET;So;0;ON;;;;;N;;;;; 1F3BB;VIOLIN;So;0;ON;;;;;N;;;;; 1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;; 1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;; 1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;; 1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;; 1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;; 1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;; 1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;; 1F3C3;RUNNER;So;0;ON;;;;;N;;;;; 1F3C4;SURFER;So;0;ON;;;;;N;;;;; 1F3C5;SPORTS MEDAL;So;0;ON;;;;;N;;;;; 1F3C6;TROPHY;So;0;ON;;;;;N;;;;; 1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;; 1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;; 1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;; 1F3CA;SWIMMER;So;0;ON;;;;;N;;;;; 1F3CB;WEIGHT LIFTER;So;0;ON;;;;;N;;;;; 1F3CC;GOLFER;So;0;ON;;;;;N;;;;; 1F3CD;RACING MOTORCYCLE;So;0;ON;;;;;N;;;;; 1F3CE;RACING CAR;So;0;ON;;;;;N;;;;; 1F3D4;SNOW CAPPED MOUNTAIN;So;0;ON;;;;;N;;;;; 1F3D5;CAMPING;So;0;ON;;;;;N;;;;; 1F3D6;BEACH WITH UMBRELLA;So;0;ON;;;;;N;;;;; 1F3D7;BUILDING CONSTRUCTION;So;0;ON;;;;;N;;;;; 1F3D8;HOUSE BUILDINGS;So;0;ON;;;;;N;;;;; 1F3D9;CITYSCAPE;So;0;ON;;;;;N;;;;; 1F3DA;DERELICT HOUSE BUILDING;So;0;ON;;;;;N;;;;; 1F3DB;CLASSICAL BUILDING;So;0;ON;;;;;N;;;;; 1F3DC;DESERT;So;0;ON;;;;;N;;;;; 1F3DD;DESERT ISLAND;So;0;ON;;;;;N;;;;; 1F3DE;NATIONAL PARK;So;0;ON;;;;;N;;;;; 1F3DF;STADIUM;So;0;ON;;;;;N;;;;; 1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;; 1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;; 1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;; 1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;; 1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;; 1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;; 1F3E6;BANK;So;0;ON;;;;;N;;;;; 1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;; 1F3E8;HOTEL;So;0;ON;;;;;N;;;;; 1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;; 1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;; 1F3EB;SCHOOL;So;0;ON;;;;;N;;;;; 1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;; 1F3ED;FACTORY;So;0;ON;;;;;N;;;;; 1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;; 1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;; 1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;; 1F3F1;WHITE PENNANT;So;0;ON;;;;;N;;;;; 1F3F2;BLACK PENNANT;So;0;ON;;;;;N;;;;; 1F3F3;WAVING WHITE FLAG;So;0;ON;;;;;N;;;;; 1F3F4;WAVING BLACK FLAG;So;0;ON;;;;;N;;;;; 1F3F5;ROSETTE;So;0;ON;;;;;N;;;;; 1F3F6;BLACK ROSETTE;So;0;ON;;;;;N;;;;; 1F3F7;LABEL;So;0;ON;;;;;N;;;;; 1F400;RAT;So;0;ON;;;;;N;;;;; 1F401;MOUSE;So;0;ON;;;;;N;;;;; 1F402;OX;So;0;ON;;;;;N;;;;; 1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;; 1F404;COW;So;0;ON;;;;;N;;;;; 1F405;TIGER;So;0;ON;;;;;N;;;;; 1F406;LEOPARD;So;0;ON;;;;;N;;;;; 1F407;RABBIT;So;0;ON;;;;;N;;;;; 1F408;CAT;So;0;ON;;;;;N;;;;; 1F409;DRAGON;So;0;ON;;;;;N;;;;; 1F40A;CROCODILE;So;0;ON;;;;;N;;;;; 1F40B;WHALE;So;0;ON;;;;;N;;;;; 1F40C;SNAIL;So;0;ON;;;;;N;;;;; 1F40D;SNAKE;So;0;ON;;;;;N;;;;; 1F40E;HORSE;So;0;ON;;;;;N;;;;; 1F40F;RAM;So;0;ON;;;;;N;;;;; 1F410;GOAT;So;0;ON;;;;;N;;;;; 1F411;SHEEP;So;0;ON;;;;;N;;;;; 1F412;MONKEY;So;0;ON;;;;;N;;;;; 1F413;ROOSTER;So;0;ON;;;;;N;;;;; 1F414;CHICKEN;So;0;ON;;;;;N;;;;; 1F415;DOG;So;0;ON;;;;;N;;;;; 1F416;PIG;So;0;ON;;;;;N;;;;; 1F417;BOAR;So;0;ON;;;;;N;;;;; 1F418;ELEPHANT;So;0;ON;;;;;N;;;;; 1F419;OCTOPUS;So;0;ON;;;;;N;;;;; 1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;; 1F41B;BUG;So;0;ON;;;;;N;;;;; 1F41C;ANT;So;0;ON;;;;;N;;;;; 1F41D;HONEYBEE;So;0;ON;;;;;N;;;;; 1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;; 1F41F;FISH;So;0;ON;;;;;N;;;;; 1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;; 1F421;BLOWFISH;So;0;ON;;;;;N;;;;; 1F422;TURTLE;So;0;ON;;;;;N;;;;; 1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;; 1F424;BABY CHICK;So;0;ON;;;;;N;;;;; 1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;; 1F426;BIRD;So;0;ON;;;;;N;;;;; 1F427;PENGUIN;So;0;ON;;;;;N;;;;; 1F428;KOALA;So;0;ON;;;;;N;;;;; 1F429;POODLE;So;0;ON;;;;;N;;;;; 1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;; 1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;; 1F42C;DOLPHIN;So;0;ON;;;;;N;;;;; 1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;; 1F42E;COW FACE;So;0;ON;;;;;N;;;;; 1F42F;TIGER FACE;So;0;ON;;;;;N;;;;; 1F430;RABBIT FACE;So;0;ON;;;;;N;;;;; 1F431;CAT FACE;So;0;ON;;;;;N;;;;; 1F432;DRAGON FACE;So;0;ON;;;;;N;;;;; 1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;; 1F434;HORSE FACE;So;0;ON;;;;;N;;;;; 1F435;MONKEY FACE;So;0;ON;;;;;N;;;;; 1F436;DOG FACE;So;0;ON;;;;;N;;;;; 1F437;PIG FACE;So;0;ON;;;;;N;;;;; 1F438;FROG FACE;So;0;ON;;;;;N;;;;; 1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;; 1F43A;WOLF FACE;So;0;ON;;;;;N;;;;; 1F43B;BEAR FACE;So;0;ON;;;;;N;;;;; 1F43C;PANDA FACE;So;0;ON;;;;;N;;;;; 1F43D;PIG NOSE;So;0;ON;;;;;N;;;;; 1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;; 1F43F;CHIPMUNK;So;0;ON;;;;;N;;;;; 1F440;EYES;So;0;ON;;;;;N;;;;; 1F441;EYE;So;0;ON;;;;;N;;;;; 1F442;EAR;So;0;ON;;;;;N;;;;; 1F443;NOSE;So;0;ON;;;;;N;;;;; 1F444;MOUTH;So;0;ON;;;;;N;;;;; 1F445;TONGUE;So;0;ON;;;;;N;;;;; 1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;; 1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;; 1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;; 1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;; 1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; 1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;; 1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;; 1F451;CROWN;So;0;ON;;;;;N;;;;; 1F452;WOMANS HAT;So;0;ON;;;;;N;;;;; 1F453;EYEGLASSES;So;0;ON;;;;;N;;;;; 1F454;NECKTIE;So;0;ON;;;;;N;;;;; 1F455;T-SHIRT;So;0;ON;;;;;N;;;;; 1F456;JEANS;So;0;ON;;;;;N;;;;; 1F457;DRESS;So;0;ON;;;;;N;;;;; 1F458;KIMONO;So;0;ON;;;;;N;;;;; 1F459;BIKINI;So;0;ON;;;;;N;;;;; 1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;; 1F45B;PURSE;So;0;ON;;;;;N;;;;; 1F45C;HANDBAG;So;0;ON;;;;;N;;;;; 1F45D;POUCH;So;0;ON;;;;;N;;;;; 1F45E;MANS SHOE;So;0;ON;;;;;N;;;;; 1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;; 1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;; 1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;; 1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;; 1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;; 1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F466;BOY;So;0;ON;;;;;N;;;;; 1F467;GIRL;So;0;ON;;;;;N;;;;; 1F468;MAN;So;0;ON;;;;;N;;;;; 1F469;WOMAN;So;0;ON;;;;;N;;;;; 1F46A;FAMILY;So;0;ON;;;;;N;;;;; 1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;; 1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;; 1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;; 1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;; 1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;; 1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;; 1F474;OLDER MAN;So;0;ON;;;;;N;;;;; 1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;; 1F476;BABY;So;0;ON;;;;;N;;;;; 1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;; 1F478;PRINCESS;So;0;ON;;;;;N;;;;; 1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;; 1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;; 1F47B;GHOST;So;0;ON;;;;;N;;;;; 1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;; 1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;; 1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;; 1F47F;IMP;So;0;ON;;;;;N;;;;; 1F480;SKULL;So;0;ON;;;;;N;;;;; 1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;; 1F482;GUARDSMAN;So;0;ON;;;;;N;;;;; 1F483;DANCER;So;0;ON;;;;;N;;;;; 1F484;LIPSTICK;So;0;ON;;;;;N;;;;; 1F485;NAIL POLISH;So;0;ON;;;;;N;;;;; 1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;; 1F487;HAIRCUT;So;0;ON;;;;;N;;;;; 1F488;BARBER POLE;So;0;ON;;;;;N;;;;; 1F489;SYRINGE;So;0;ON;;;;;N;;;;; 1F48A;PILL;So;0;ON;;;;;N;;;;; 1F48B;KISS MARK;So;0;ON;;;;;N;;;;; 1F48C;LOVE LETTER;So;0;ON;;;;;N;;;;; 1F48D;RING;So;0;ON;;;;;N;;;;; 1F48E;GEM STONE;So;0;ON;;;;;N;;;;; 1F48F;KISS;So;0;ON;;;;;N;;;;; 1F490;BOUQUET;So;0;ON;;;;;N;;;;; 1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;; 1F492;WEDDING;So;0;ON;;;;;N;;;;; 1F493;BEATING HEART;So;0;ON;;;;;N;;;;; 1F494;BROKEN HEART;So;0;ON;;;;;N;;;;; 1F495;TWO HEARTS;So;0;ON;;;;;N;;;;; 1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;; 1F497;GROWING HEART;So;0;ON;;;;;N;;;;; 1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;; 1F499;BLUE HEART;So;0;ON;;;;;N;;;;; 1F49A;GREEN HEART;So;0;ON;;;;;N;;;;; 1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;; 1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;; 1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;; 1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;; 1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;; 1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;; 1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;; 1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;; 1F4A3;BOMB;So;0;ON;;;;;N;;;;; 1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;; 1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;; 1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;; 1F4A7;DROPLET;So;0;ON;;;;;N;;;;; 1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;; 1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;; 1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;; 1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;; 1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;; 1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;; 1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;; 1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;; 1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;; 1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;; 1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;; 1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;; 1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;; 1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;; 1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;; 1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;; 1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;; 1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;; 1F4BA;SEAT;So;0;ON;;;;;N;;;;; 1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; 1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;; 1F4BD;MINIDISC;So;0;ON;;;;;N;;;;; 1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;; 1F4C0;DVD;So;0;ON;;;;;N;;;;; 1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;; 1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;; 1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;; 1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;; 1F4C5;CALENDAR;So;0;ON;;;;;N;;;;; 1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;; 1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;; 1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;; 1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;; 1F4CA;BAR CHART;So;0;ON;;;;;N;;;;; 1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;; 1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;; 1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;; 1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;; 1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;; 1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;; 1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;; 1F4D2;LEDGER;So;0;ON;;;;;N;;;;; 1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;; 1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;; 1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;; 1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;; 1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;; 1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;; 1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;; 1F4DA;BOOKS;So;0;ON;;;;;N;;;;; 1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;; 1F4DC;SCROLL;So;0;ON;;;;;N;;;;; 1F4DD;MEMO;So;0;ON;;;;;N;;;;; 1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F4DF;PAGER;So;0;ON;;;;;N;;;;; 1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;; 1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;; 1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;; 1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;; 1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;; 1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;; 1F4E6;PACKAGE;So;0;ON;;;;;N;;;;; 1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;; 1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;; 1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; 1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; 1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; 1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; 1F4EE;POSTBOX;So;0;ON;;;;;N;;;;; 1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;; 1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;; 1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;; 1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;; 1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;; 1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;; 1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;; 1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;; 1F4F7;CAMERA;So;0;ON;;;;;N;;;;; 1F4F8;CAMERA WITH FLASH;So;0;ON;;;;;N;;;;; 1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;; 1F4FA;TELEVISION;So;0;ON;;;;;N;;;;; 1F4FB;RADIO;So;0;ON;;;;;N;;;;; 1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;; 1F4FD;FILM PROJECTOR;So;0;ON;;;;;N;;;;; 1F4FE;PORTABLE STEREO;So;0;ON;;;;;N;;;;; 1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;; 1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;; 1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; 1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; 1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; 1F508;SPEAKER;So;0;ON;;;;;N;;;;; 1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; 1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; 1F50B;BATTERY;So;0;ON;;;;;N;;;;; 1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;; 1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; 1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; 1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;; 1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;; 1F511;KEY;So;0;ON;;;;;N;;;;; 1F512;LOCK;So;0;ON;;;;;N;;;;; 1F513;OPEN LOCK;So;0;ON;;;;;N;;;;; 1F514;BELL;So;0;ON;;;;;N;;;;; 1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; 1F516;BOOKMARK;So;0;ON;;;;;N;;;;; 1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;; 1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;; 1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;; 1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;; 1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;; 1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;; 1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;; 1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;; 1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;ON;;;;;N;;;;; 1F525;FIRE;So;0;ON;;;;;N;;;;; 1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;; 1F527;WRENCH;So;0;ON;;;;;N;;;;; 1F528;HAMMER;So;0;ON;;;;;N;;;;; 1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;; 1F52A;HOCHO;So;0;ON;;;;;N;;;;; 1F52B;PISTOL;So;0;ON;;;;;N;;;;; 1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;; 1F52D;TELESCOPE;So;0;ON;;;;;N;;;;; 1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;; 1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;; 1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;; 1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;; 1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;; 1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;; 1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;; 1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;; 1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;; 1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;; 1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;; 1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53E;LOWER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F53F;UPPER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F540;CIRCLED CROSS POMMEE;So;0;ON;;;;;N;;;;; 1F541;CROSS POMMEE WITH HALF-CIRCLE BELOW;So;0;ON;;;;;N;;;;; 1F542;CROSS POMMEE;So;0;ON;;;;;N;;;;; 1F543;NOTCHED LEFT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; 1F544;NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; 1F545;SYMBOL FOR MARKS CHAPTER;So;0;ON;;;;;N;;;;; 1F546;WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 1F547;HEAVY LATIN CROSS;So;0;ON;;;;;N;;;;; 1F548;CELTIC CROSS;So;0;ON;;;;;N;;;;; 1F549;OM SYMBOL;So;0;ON;;;;;N;;;;; 1F54A;DOVE OF PEACE;So;0;ON;;;;;N;;;;; 1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;; 1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;; 1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;; 1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;; 1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;; 1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;; 1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;; 1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;; 1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;; 1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;; 1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;; 1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;; 1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;; 1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;; 1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;; 1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;; 1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;; 1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;; 1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;; 1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;; 1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;; 1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;; 1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;; 1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;; 1F568;RIGHT SPEAKER;So;0;ON;;;;;N;;;;; 1F569;RIGHT SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; 1F56A;RIGHT SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; 1F56B;BULLHORN;So;0;ON;;;;;N;;;;; 1F56C;BULLHORN WITH SOUND WAVES;So;0;ON;;;;;N;;;;; 1F56D;RINGING BELL;So;0;ON;;;;;N;;;;; 1F56E;BOOK;So;0;ON;;;;;N;;;;; 1F56F;CANDLE;So;0;ON;;;;;N;;;;; 1F570;MANTELPIECE CLOCK;So;0;ON;;;;;N;;;;; 1F571;BLACK SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 1F572;NO PIRACY;So;0;ON;;;;;N;;;;; 1F573;HOLE;So;0;ON;;;;;N;;;;; 1F574;MAN IN BUSINESS SUIT LEVITATING;So;0;ON;;;;;N;;;;; 1F575;SLEUTH OR SPY;So;0;ON;;;;;N;;;;; 1F576;DARK SUNGLASSES;So;0;ON;;;;;N;;;;; 1F577;SPIDER;So;0;ON;;;;;N;;;;; 1F578;SPIDER WEB;So;0;ON;;;;;N;;;;; 1F579;JOYSTICK;So;0;ON;;;;;N;;;;; 1F57B;LEFT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F57C;TELEPHONE RECEIVER WITH PAGE;So;0;ON;;;;;N;;;;; 1F57D;RIGHT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F57E;WHITE TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; 1F57F;BLACK TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; 1F580;TELEPHONE ON TOP OF MODEM;So;0;ON;;;;;N;;;;; 1F581;CLAMSHELL MOBILE PHONE;So;0;ON;;;;;N;;;;; 1F582;BACK OF ENVELOPE;So;0;ON;;;;;N;;;;; 1F583;STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; 1F584;ENVELOPE WITH LIGHTNING;So;0;ON;;;;;N;;;;; 1F585;FLYING ENVELOPE;So;0;ON;;;;;N;;;;; 1F586;PEN OVER STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; 1F587;LINKED PAPERCLIPS;So;0;ON;;;;;N;;;;; 1F588;BLACK PUSHPIN;So;0;ON;;;;;N;;;;; 1F589;LOWER LEFT PENCIL;So;0;ON;;;;;N;;;;; 1F58A;LOWER LEFT BALLPOINT PEN;So;0;ON;;;;;N;;;;; 1F58B;LOWER LEFT FOUNTAIN PEN;So;0;ON;;;;;N;;;;; 1F58C;LOWER LEFT PAINTBRUSH;So;0;ON;;;;;N;;;;; 1F58D;LOWER LEFT CRAYON;So;0;ON;;;;;N;;;;; 1F58E;LEFT WRITING HAND;So;0;ON;;;;;N;;;;; 1F58F;TURNED OK HAND SIGN;So;0;ON;;;;;N;;;;; 1F590;RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; 1F591;REVERSED RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; 1F592;REVERSED THUMBS UP SIGN;So;0;ON;;;;;N;;;;; 1F593;REVERSED THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; 1F594;REVERSED VICTORY HAND;So;0;ON;;;;;N;;;;; 1F595;REVERSED HAND WITH MIDDLE FINGER EXTENDED;So;0;ON;;;;;N;;;;; 1F596;RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS;So;0;ON;;;;;N;;;;; 1F597;WHITE DOWN POINTING LEFT HAND INDEX;So;0;ON;;;;;N;;;;; 1F598;SIDEWAYS WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F599;SIDEWAYS WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59A;SIDEWAYS BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59B;SIDEWAYS BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59C;BLACK LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F59D;BLACK RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F59E;SIDEWAYS WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59F;SIDEWAYS WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A0;SIDEWAYS BLACK UP POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A1;SIDEWAYS BLACK DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A2;BLACK UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F5A3;BLACK DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F5A5;DESKTOP COMPUTER;So;0;ON;;;;;N;;;;; 1F5A6;KEYBOARD AND MOUSE;So;0;ON;;;;;N;;;;; 1F5A7;THREE NETWORKED COMPUTERS;So;0;ON;;;;;N;;;;; 1F5A8;PRINTER;So;0;ON;;;;;N;;;;; 1F5A9;POCKET CALCULATOR;So;0;ON;;;;;N;;;;; 1F5AA;BLACK HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AB;WHITE HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AC;SOFT SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AD;TAPE CARTRIDGE;So;0;ON;;;;;N;;;;; 1F5AE;WIRED KEYBOARD;So;0;ON;;;;;N;;;;; 1F5AF;ONE BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B0;TWO BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B1;THREE BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B2;TRACKBALL;So;0;ON;;;;;N;;;;; 1F5B3;OLD PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; 1F5B4;HARD DISK;So;0;ON;;;;;N;;;;; 1F5B5;SCREEN;So;0;ON;;;;;N;;;;; 1F5B6;PRINTER ICON;So;0;ON;;;;;N;;;;; 1F5B7;FAX ICON;So;0;ON;;;;;N;;;;; 1F5B8;OPTICAL DISC ICON;So;0;ON;;;;;N;;;;; 1F5B9;DOCUMENT WITH TEXT;So;0;ON;;;;;N;;;;; 1F5BA;DOCUMENT WITH TEXT AND PICTURE;So;0;ON;;;;;N;;;;; 1F5BB;DOCUMENT WITH PICTURE;So;0;ON;;;;;N;;;;; 1F5BC;FRAME WITH PICTURE;So;0;ON;;;;;N;;;;; 1F5BD;FRAME WITH TILES;So;0;ON;;;;;N;;;;; 1F5BE;FRAME WITH AN X;So;0;ON;;;;;N;;;;; 1F5BF;BLACK FOLDER;So;0;ON;;;;;N;;;;; 1F5C0;FOLDER;So;0;ON;;;;;N;;;;; 1F5C1;OPEN FOLDER;So;0;ON;;;;;N;;;;; 1F5C2;CARD INDEX DIVIDERS;So;0;ON;;;;;N;;;;; 1F5C3;CARD FILE BOX;So;0;ON;;;;;N;;;;; 1F5C4;FILE CABINET;So;0;ON;;;;;N;;;;; 1F5C5;EMPTY NOTE;So;0;ON;;;;;N;;;;; 1F5C6;EMPTY NOTE PAGE;So;0;ON;;;;;N;;;;; 1F5C7;EMPTY NOTE PAD;So;0;ON;;;;;N;;;;; 1F5C8;NOTE;So;0;ON;;;;;N;;;;; 1F5C9;NOTE PAGE;So;0;ON;;;;;N;;;;; 1F5CA;NOTE PAD;So;0;ON;;;;;N;;;;; 1F5CB;EMPTY DOCUMENT;So;0;ON;;;;;N;;;;; 1F5CC;EMPTY PAGE;So;0;ON;;;;;N;;;;; 1F5CD;EMPTY PAGES;So;0;ON;;;;;N;;;;; 1F5CE;DOCUMENT;So;0;ON;;;;;N;;;;; 1F5CF;PAGE;So;0;ON;;;;;N;;;;; 1F5D0;PAGES;So;0;ON;;;;;N;;;;; 1F5D1;WASTEBASKET;So;0;ON;;;;;N;;;;; 1F5D2;SPIRAL NOTE PAD;So;0;ON;;;;;N;;;;; 1F5D3;SPIRAL CALENDAR PAD;So;0;ON;;;;;N;;;;; 1F5D4;DESKTOP WINDOW;So;0;ON;;;;;N;;;;; 1F5D5;MINIMIZE;So;0;ON;;;;;N;;;;; 1F5D6;MAXIMIZE;So;0;ON;;;;;N;;;;; 1F5D7;OVERLAP;So;0;ON;;;;;N;;;;; 1F5D8;CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F5D9;CANCELLATION X;So;0;ON;;;;;N;;;;; 1F5DA;INCREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; 1F5DB;DECREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; 1F5DC;COMPRESSION;So;0;ON;;;;;N;;;;; 1F5DD;OLD KEY;So;0;ON;;;;;N;;;;; 1F5DE;ROLLED-UP NEWSPAPER;So;0;ON;;;;;N;;;;; 1F5DF;PAGE WITH CIRCLED TEXT;So;0;ON;;;;;N;;;;; 1F5E0;STOCK CHART;So;0;ON;;;;;N;;;;; 1F5E1;DAGGER KNIFE;So;0;ON;;;;;N;;;;; 1F5E2;LIPS;So;0;ON;;;;;N;;;;; 1F5E3;SPEAKING HEAD IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F5E4;THREE RAYS ABOVE;So;0;ON;;;;;N;;;;; 1F5E5;THREE RAYS BELOW;So;0;ON;;;;;N;;;;; 1F5E6;THREE RAYS LEFT;So;0;ON;;;;;N;;;;; 1F5E7;THREE RAYS RIGHT;So;0;ON;;;;;N;;;;; 1F5E8;LEFT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; 1F5E9;RIGHT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; 1F5EA;TWO SPEECH BUBBLES;So;0;ON;;;;;N;;;;; 1F5EB;THREE SPEECH BUBBLES;So;0;ON;;;;;N;;;;; 1F5EC;LEFT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; 1F5ED;RIGHT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; 1F5EE;LEFT ANGER BUBBLE;So;0;ON;;;;;N;;;;; 1F5EF;RIGHT ANGER BUBBLE;So;0;ON;;;;;N;;;;; 1F5F0;MOOD BUBBLE;So;0;ON;;;;;N;;;;; 1F5F1;LIGHTNING MOOD BUBBLE;So;0;ON;;;;;N;;;;; 1F5F2;LIGHTNING MOOD;So;0;ON;;;;;N;;;;; 1F5F3;BALLOT BOX WITH BALLOT;So;0;ON;;;;;N;;;;; 1F5F4;BALLOT SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F5;BALLOT BOX WITH SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F6;BALLOT BOLD SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F7;BALLOT BOX WITH BOLD SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F8;LIGHT CHECK MARK;So;0;ON;;;;;N;;;;; 1F5F9;BALLOT BOX WITH BOLD CHECK;So;0;ON;;;;;N;;;;; 1F5FA;WORLD MAP;So;0;ON;;;;;N;;;;; 1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;; 1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;; 1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;; 1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;; 1F5FF;MOYAI;So;0;ON;;;;;N;;;;; 1F600;GRINNING FACE;So;0;ON;;;;;N;;;;; 1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; 1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;; 1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; 1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; 1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;; 1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;; 1F609;WINKING FACE;So;0;ON;;;;;N;;;;; 1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;; 1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;; 1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; 1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;; 1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;; 1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;; 1F611;EXPRESSIONLESS FACE;So;0;ON;;;;;N;;;;; 1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;; 1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;; 1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;; 1F615;CONFUSED FACE;So;0;ON;;;;;N;;;;; 1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;; 1F617;KISSING FACE;So;0;ON;;;;;N;;;;; 1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;; 1F619;KISSING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; 1F61B;FACE WITH STUCK-OUT TONGUE;So;0;ON;;;;;N;;;;; 1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;; 1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; 1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;; 1F61F;WORRIED FACE;So;0;ON;;;;;N;;;;; 1F620;ANGRY FACE;So;0;ON;;;;;N;;;;; 1F621;POUTING FACE;So;0;ON;;;;;N;;;;; 1F622;CRYING FACE;So;0;ON;;;;;N;;;;; 1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;; 1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;; 1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;; 1F626;FROWNING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F627;ANGUISHED FACE;So;0;ON;;;;;N;;;;; 1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;; 1F629;WEARY FACE;So;0;ON;;;;;N;;;;; 1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;; 1F62B;TIRED FACE;So;0;ON;;;;;N;;;;; 1F62C;GRIMACING FACE;So;0;ON;;;;;N;;;;; 1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;; 1F62E;FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F62F;HUSHED FACE;So;0;ON;;;;;N;;;;; 1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; 1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;; 1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;; 1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;; 1F634;SLEEPING FACE;So;0;ON;;;;;N;;;;; 1F635;DIZZY FACE;So;0;ON;;;;;N;;;;; 1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;; 1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;; 1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; 1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; 1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;; 1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; 1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;; 1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;; 1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;; 1F641;SLIGHTLY FROWNING FACE;So;0;ON;;;;;N;;;;; 1F642;SLIGHTLY SMILING FACE;So;0;ON;;;;;N;;;;; 1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;; 1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;; 1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;; 1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;; 1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;; 1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;; 1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;; 1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;; 1F650;NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F651;SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F652;NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F653;SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F654;TURNED NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F655;TURNED SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F656;TURNED NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F657;TURNED SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F658;NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F659;SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65A;NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65B;SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65C;HEAVY NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65D;HEAVY SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65E;HEAVY NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65F;HEAVY SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F660;NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F661;SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F662;NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F663;SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F664;HEAVY NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F665;HEAVY SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F666;HEAVY NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F667;HEAVY SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F668;HOLLOW QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; 1F669;HOLLOW QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 1F66A;SOLID QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; 1F66B;SOLID QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 1F66C;LEFTWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66D;UPWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66E;RIGHTWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66F;DOWNWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F670;SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F671;HEAVY SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F672;LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F673;HEAVY LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F674;HEAVY AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; 1F675;SWASH AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; 1F676;SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F677;SANS-SERIF HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F678;SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F679;HEAVY INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67A;SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67B;HEAVY SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67C;VERY HEAVY SOLIDUS;So;0;ON;;;;;N;;;;; 1F67D;VERY HEAVY REVERSE SOLIDUS;So;0;ON;;;;;N;;;;; 1F67E;CHECKER BOARD;So;0;ON;;;;;N;;;;; 1F67F;REVERSE CHECKER BOARD;So;0;ON;;;;;N;;;;; 1F680;ROCKET;So;0;ON;;;;;N;;;;; 1F681;HELICOPTER;So;0;ON;;;;;N;;;;; 1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;; 1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;; 1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;; 1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;; 1F686;TRAIN;So;0;ON;;;;;N;;;;; 1F687;METRO;So;0;ON;;;;;N;;;;; 1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;; 1F689;STATION;So;0;ON;;;;;N;;;;; 1F68A;TRAM;So;0;ON;;;;;N;;;;; 1F68B;TRAM CAR;So;0;ON;;;;;N;;;;; 1F68C;BUS;So;0;ON;;;;;N;;;;; 1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;; 1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;; 1F68F;BUS STOP;So;0;ON;;;;;N;;;;; 1F690;MINIBUS;So;0;ON;;;;;N;;;;; 1F691;AMBULANCE;So;0;ON;;;;;N;;;;; 1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;; 1F693;POLICE CAR;So;0;ON;;;;;N;;;;; 1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;; 1F695;TAXI;So;0;ON;;;;;N;;;;; 1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;; 1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;; 1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;; 1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;; 1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;; 1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;; 1F69C;TRACTOR;So;0;ON;;;;;N;;;;; 1F69D;MONORAIL;So;0;ON;;;;;N;;;;; 1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;; 1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;; 1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;; 1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;; 1F6A2;SHIP;So;0;ON;;;;;N;;;;; 1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;; 1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;; 1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; 1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; 1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;; 1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;; 1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;; 1F6AA;DOOR;So;0;ON;;;;;N;;;;; 1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;; 1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;; 1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;; 1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;; 1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B2;BICYCLE;So;0;ON;;;;;N;;;;; 1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;; 1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;; 1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;; 1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;; 1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;; 1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;; 1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;; 1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;; 1F6BB;RESTROOM;So;0;ON;;;;;N;;;;; 1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;; 1F6BD;TOILET;So;0;ON;;;;;N;;;;; 1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;; 1F6BF;SHOWER;So;0;ON;;;;;N;;;;; 1F6C0;BATH;So;0;ON;;;;;N;;;;; 1F6C1;BATHTUB;So;0;ON;;;;;N;;;;; 1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;; 1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;; 1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;; 1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;; 1F6C6;TRIANGLE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 1F6C7;PROHIBITED SIGN;So;0;ON;;;;;N;;;;; 1F6C8;CIRCLED INFORMATION SOURCE;So;0;ON;;;;;N;;;;; 1F6C9;BOYS SYMBOL;So;0;ON;;;;;N;;;;; 1F6CA;GIRLS SYMBOL;So;0;ON;;;;;N;;;;; 1F6CB;COUCH AND LAMP;So;0;ON;;;;;N;;;;; 1F6CC;SLEEPING ACCOMMODATION;So;0;ON;;;;;N;;;;; 1F6CD;SHOPPING BAGS;So;0;ON;;;;;N;;;;; 1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;; 1F6CF;BED;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; 1F6E3;MOTORWAY;So;0;ON;;;;;N;;;;; 1F6E4;RAILWAY TRACK;So;0;ON;;;;;N;;;;; 1F6E5;MOTOR BOAT;So;0;ON;;;;;N;;;;; 1F6E6;UP-POINTING MILITARY AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E7;UP-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E8;UP-POINTING SMALL AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E9;SMALL AIRPLANE;So;0;ON;;;;;N;;;;; 1F6EA;NORTHEAST-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; 1F6EB;AIRPLANE DEPARTURE;So;0;ON;;;;;N;;;;; 1F6EC;AIRPLANE ARRIVING;So;0;ON;;;;;N;;;;; 1F6F0;SATELLITE;So;0;ON;;;;;N;;;;; 1F6F1;ONCOMING FIRE ENGINE;So;0;ON;;;;;N;;;;; 1F6F2;DIESEL LOCOMOTIVE;So;0;ON;;;;;N;;;;; 1F6F3;PASSENGER SHIP;So;0;ON;;;;;N;;;;; 1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; 1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; 1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; 1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;; 1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;; 1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;; 1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;; 1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;; 1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;; 1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;; 1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;; 1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;; 1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;; 1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;; 1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;; 1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;; 1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;; 1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;; 1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;; 1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;; 1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;; 1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;; 1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;; 1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;; 1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;; 1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;; 1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;; 1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;; 1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;; 1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;; 1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;; 1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;; 1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;; 1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;; 1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;; 1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;; 1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;; 1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; 1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; 1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;; 1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;; 1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;; 1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;; 1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;; 1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;; 1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;; 1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;; 1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;; 1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;; 1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;; 1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;; 1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;; 1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;; 1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;; 1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;; 1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;; 1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;; 1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;; 1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;; 1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;; 1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;; 1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;; 1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;; 1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;; 1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;; 1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;; 1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;; 1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;; 1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;; 1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;; 1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;; 1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;; 1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;; 1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;; 1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;; 1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;; 1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;; 1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;; 1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;; 1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;; 1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;; 1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;; 1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;; 1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;; 1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;; 1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;; 1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;; 1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;; 1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;; 1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;; 1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;; 1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;; 1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;; 1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;; 1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;; 1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;; 1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;; 1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;; 1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;; 1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;; 1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;; 1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;; 1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;; 1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;; 1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;; 1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;; 1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;; 1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;; 1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;; 1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;; 1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;; 1F780;BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F781;BLACK UP-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F782;BLACK RIGHT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F783;BLACK DOWN-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F784;BLACK SLIGHTLY SMALL CIRCLE;So;0;ON;;;;;N;;;;; 1F785;MEDIUM BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F786;BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F787;HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F788;VERY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F789;EXTREMELY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F78A;WHITE CIRCLE CONTAINING BLACK SMALL CIRCLE;So;0;ON;;;;;N;;;;; 1F78B;ROUND TARGET;So;0;ON;;;;;N;;;;; 1F78C;BLACK TINY SQUARE;So;0;ON;;;;;N;;;;; 1F78D;BLACK SLIGHTLY SMALL SQUARE;So;0;ON;;;;;N;;;;; 1F78E;LIGHT WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F78F;MEDIUM WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F790;BOLD WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F791;HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F792;VERY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F793;EXTREMELY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F794;WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 1F795;WHITE SQUARE CONTAINING BLACK MEDIUM SQUARE;So;0;ON;;;;;N;;;;; 1F796;SQUARE TARGET;So;0;ON;;;;;N;;;;; 1F797;BLACK TINY DIAMOND;So;0;ON;;;;;N;;;;; 1F798;BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F799;BLACK MEDIUM SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F79A;WHITE DIAMOND CONTAINING BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F79B;WHITE DIAMOND CONTAINING BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 1F79C;DIAMOND TARGET;So;0;ON;;;;;N;;;;; 1F79D;BLACK TINY LOZENGE;So;0;ON;;;;;N;;;;; 1F79E;BLACK VERY SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F79F;BLACK MEDIUM SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F7A0;WHITE LOZENGE CONTAINING BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F7A1;THIN GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A2;LIGHT GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A3;MEDIUM GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A4;BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A5;VERY BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A6;VERY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A7;EXTREMELY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A8;THIN SALTIRE;So;0;ON;;;;;N;;;;; 1F7A9;LIGHT SALTIRE;So;0;ON;;;;;N;;;;; 1F7AA;MEDIUM SALTIRE;So;0;ON;;;;;N;;;;; 1F7AB;BOLD SALTIRE;So;0;ON;;;;;N;;;;; 1F7AC;HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AD;VERY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AE;EXTREMELY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AF;LIGHT FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B0;MEDIUM FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B1;BOLD FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B2;HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B3;VERY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B4;EXTREMELY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B5;LIGHT SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B6;MEDIUM SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B7;BOLD SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B8;HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B9;VERY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BA;EXTREMELY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BB;LIGHT EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BC;MEDIUM EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BD;BOLD EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BE;HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BF;VERY HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7C0;LIGHT THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C1;MEDIUM THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C2;THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C3;MEDIUM THREE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C4;LIGHT FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C5;MEDIUM FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C6;FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C7;MEDIUM FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C8;REVERSE LIGHT FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C9;LIGHT FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CA;HEAVY FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CB;MEDIUM SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CC;HEAVY SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CD;SIX POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7CE;MEDIUM EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CF;HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D0;VERY HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D1;HEAVY EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7D2;LIGHT TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D3;HEAVY TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D4;HEAVY TWELVE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F803;DOWNWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F804;LEFTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F805;UPWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F806;RIGHTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F807;DOWNWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F808;LEFTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F809;UPWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F80A;RIGHTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F80B;DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F810;LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F811;UPWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F812;RIGHTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F813;DOWNWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F814;LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F815;UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F816;RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F817;DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F818;HEAVY LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F819;HEAVY UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81A;HEAVY RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81B;HEAVY DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81C;HEAVY LEFTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81D;HEAVY UPWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81E;HEAVY RIGHTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81F;HEAVY DOWNWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F820;LEFTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F821;UPWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F822;RIGHTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F823;DOWNWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F824;LEFTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F825;UPWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F826;RIGHTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F827;DOWNWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F828;LEFTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F829;UPWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82A;RIGHTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82B;DOWNWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82C;LEFTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82D;UPWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82E;RIGHTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82F;DOWNWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F830;LEFTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F831;UPWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F832;RIGHTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F833;DOWNWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F834;LEFTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F835;UPWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F836;RIGHTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F837;DOWNWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F838;LEFTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F839;UPWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83A;RIGHTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83B;DOWNWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83C;LEFTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83D;UPWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83E;RIGHTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83F;DOWNWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F840;LEFTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F841;UPWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F842;RIGHTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F843;DOWNWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F844;LEFTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F845;UPWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F846;RIGHTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F847;DOWNWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F850;LEFTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F851;UPWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F852;RIGHTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F853;DOWNWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F854;NORTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F855;NORTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F856;SOUTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F857;SOUTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F858;LEFT RIGHT SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F859;UP DOWN SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F860;WIDE-HEADED LEFTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F861;WIDE-HEADED UPWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F862;WIDE-HEADED RIGHTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F863;WIDE-HEADED DOWNWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F864;WIDE-HEADED NORTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F865;WIDE-HEADED NORTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F866;WIDE-HEADED SOUTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F867;WIDE-HEADED SOUTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F868;WIDE-HEADED LEFTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F869;WIDE-HEADED UPWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86A;WIDE-HEADED RIGHTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86B;WIDE-HEADED DOWNWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86C;WIDE-HEADED NORTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86D;WIDE-HEADED NORTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86E;WIDE-HEADED SOUTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86F;WIDE-HEADED SOUTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; 1F870;WIDE-HEADED LEFTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F871;WIDE-HEADED UPWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F872;WIDE-HEADED RIGHTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F873;WIDE-HEADED DOWNWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F874;WIDE-HEADED NORTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F875;WIDE-HEADED NORTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F876;WIDE-HEADED SOUTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F877;WIDE-HEADED SOUTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F878;WIDE-HEADED LEFTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F879;WIDE-HEADED UPWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87A;WIDE-HEADED RIGHTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87B;WIDE-HEADED DOWNWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87C;WIDE-HEADED NORTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87D;WIDE-HEADED NORTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87E;WIDE-HEADED SOUTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87F;WIDE-HEADED SOUTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F880;WIDE-HEADED LEFTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F881;WIDE-HEADED UPWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F882;WIDE-HEADED RIGHTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F883;WIDE-HEADED DOWNWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F884;WIDE-HEADED NORTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F885;WIDE-HEADED NORTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F886;WIDE-HEADED SOUTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F887;WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F890;LEFTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F891;UPWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F892;RIGHTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F893;DOWNWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F894;LEFTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F895;UPWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F896;RIGHTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F897;DOWNWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F898;LEFTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F899;UPWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89A;RIGHTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89B;DOWNWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89C;HEAVY ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F89D;HEAVY ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; 1F89E;HEAVY ARROW SHAFT WIDTH ONE HALF;So;0;ON;;;;;N;;;;; 1F89F;HEAVY ARROW SHAFT WIDTH ONE THIRD;So;0;ON;;;;;N;;;;; 1F8A0;LEFTWARDS BOTTOM-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A1;RIGHTWARDS BOTTOM SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A2;LEFTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A3;RIGHTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A4;LEFTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A5;RIGHTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A6;LEFTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A7;RIGHTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A8;LEFTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A9;RIGHTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AA;LEFTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; 2A6D6;;Lo;0;L;;;;;N;;;;; 2A700;;Lo;0;L;;;;;N;;;;; 2B734;;Lo;0;L;;;;;N;;;;; 2B740;;Lo;0;L;;;;;N;;;;; 2B81D;;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; 2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; 2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; 2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; 2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; 2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; 2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; 2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; 2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; 2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; 2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; 2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; 2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; 2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; 2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; 2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; 2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; 2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; 2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; 2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; 2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; 2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; 2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; 2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; 2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; 2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; 2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; 2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; 2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; 2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; 2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; 2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; 2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; 2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; 2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; 2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; 2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; 2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; 2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; 2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; 2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; 2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; 2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; 2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; 2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; 2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; 2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; 2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; 2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; 2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; 2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; 2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; 2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; 2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; 2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; 2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; 2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; 2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; 2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; 2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; 2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; 2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; 2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; 2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; 2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; 2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; 2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; 2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; 2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; 2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; 2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; 2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; 2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; 2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; 2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; 2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; 2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; 2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; 2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; 2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; 2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; 2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; 2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; 2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; 2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; 2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; 2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; 2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; 2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; 2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; 2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; 2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; 2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; 2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; 2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; 2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; 2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; 2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; 2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; 2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; 2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; 2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; 2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;; 2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; 2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; 2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; 2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; 2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; 2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; 2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; 2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; 2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; 2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; 2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; 2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;; 2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; 2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; 2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; 2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; 2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; 2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; 2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; 2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; 2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; 2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; 2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; 2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; 2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; 2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; 2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; 2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; 2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; 2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; 2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; 2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; 2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; 2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; 2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; 2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; 2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; 2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; 2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; 2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;; 2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; 2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; 2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; 2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; 2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; 2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; 2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; 2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; 2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; 2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; 2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; 2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; 2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; 2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; 2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; 2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; 2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; 2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; 2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; 2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; 2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; 2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; 2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; 2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; 2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; 2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; 2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; 2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; 2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; 2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; 2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; 2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; 2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; 2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; 2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; 2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; 2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; 2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; 2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; 2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; 2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; 2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; 2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; 2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; 2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; 2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; 2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; 2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; 2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; 2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; 2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; 2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; 2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; 2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; 2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; 2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; 2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; 2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; 2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; 2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; 2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; 2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; 2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; 2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; 2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; 2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; 2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; 2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; 2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; 2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; 2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; 2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; 2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; 2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; 2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; 2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; 2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; 2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; 2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; 2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; 2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; 2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; 2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; 2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; 2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; 2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; 2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; 2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; 2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; 2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; 2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; 2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; 2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; 2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; 2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; 2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; 2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; 2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; 2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; 2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; 2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; 2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; 2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; 2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; 2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; 2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; 2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; 2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; 2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; 2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; 2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; 2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; 2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; 2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; 2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; 2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; 2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; 2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; 2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; 2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; 2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; 2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; 2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; 2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; 2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; 2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; 2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; 2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; 2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; 2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; 2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; 2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; 2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; 2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; 2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; 2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; 2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; 2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; 2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; 2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; 2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; 2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; 2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;; 2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; 2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; 2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; 2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; 2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; 2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; 2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; 2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; 2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; 2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; 2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; 2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; 2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; 2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; 2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; 2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; 2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; 2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; 2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; 2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; 2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; 2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; 2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; 2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; 2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; 2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; 2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; 2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; 2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; 2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; 2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; 2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; 2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; 2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; 2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; 2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; 2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; 2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; 2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; 2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; 2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; 2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; 2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; 2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; 2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; 2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; 2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; 2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; 2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; 2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; 2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; 2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; 2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; 2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; 2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; 2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; 2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; 2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; 2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; 2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; 2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; 2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; 2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; 2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;; 2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; 2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; 2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; 2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; 2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; 2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; 2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; 2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; 2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; 2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; 2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; 2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; 2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; 2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; 2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; 2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; 2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; 2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; 2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; 2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; 2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; 2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; 2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; 2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; 2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; 2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; 2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; 2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; 2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; 2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; 2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; 2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; 2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; 2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; 2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; 2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; 2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; 2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; 2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; 2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; 2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; 2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; 2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; 2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; 2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; 2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; 2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; 2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; 2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; 2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; 2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; 2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; 2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; 2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; 2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; 2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; 2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; 2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; 2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; 2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; 2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; 2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; 2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; 2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; 2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; 2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; 2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; 2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; 2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; 2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; 2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; 2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; 2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; 2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; 2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; 2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; 2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; 2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; 2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; 2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; 2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; 2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; 2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; 2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; 2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; 2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; 2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; 2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; 2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; 2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; 2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; 2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; 2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; 2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; 2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; 2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;; 2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; 2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; 2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; 2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; 2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; 2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; 2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; 2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; 2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; 2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; 2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; 2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; 2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; 2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; 2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; 2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; 2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; 2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; 2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; 2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; 2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; 2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; 2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; 2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; 2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; 2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; 2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; 2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; 2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; 2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; 2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; 2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; 2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; 2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; 2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; 2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; 2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; 2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; 2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; 2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; 2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; 2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; 2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; 2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; 2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; 2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; 2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; 2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; 2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; 2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; 2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; 2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; 2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; 2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; 2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; 2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; 2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; 2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; 2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; 2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; 2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; 2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; 2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; 2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; 2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; 2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; 2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; 2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; 2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; 2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; 2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; 2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; 2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; 2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; 2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; 2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; 2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; 2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; 2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; 2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; 2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; 2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; 2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; 2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; 2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; 2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; 2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; 2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; 2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; 2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; 2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; 2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; 2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; 2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;; E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;; E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;; E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;; E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;; E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;; E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;; E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;; E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;; E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;; E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;; E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;; E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;; E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;; E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;; E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;; E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;; E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;; E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;; E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;; E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;; E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;; E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;; E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;; E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;; E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;; E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;; E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;; E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;; E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;; E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;; E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;; E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;; E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;; E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;; E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;; E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;; E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;; E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;; E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;; E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;; E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;; E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;; E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;; E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;; E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;; E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;; E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;; E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;; E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;; E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;; E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;; E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;; E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;; E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;; E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;; E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;; E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;; E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;; E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;; E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;; E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;; E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;; E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;; E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;; E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;; E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;; E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;; E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;; E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;; E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;; E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;; E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;; E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;; E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;; E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;; E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;; E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;; E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;; E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;; E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;; E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;; E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;; E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;; E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;; E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;; E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;; E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;; E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;; E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;; E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;; E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;; E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;; E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;; E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;; E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;; E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;; E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;; E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;; E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;; E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;; E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;; E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;; E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;; E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;; E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;; E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;; E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;; E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;; E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;; E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;; E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;; E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;; E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;; E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;; E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;; E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;; E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;; E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;; E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;; E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;; E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;; E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;; E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;; E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;; E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;; E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;; E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;; E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;; E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;; E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;; E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;; E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;; E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;; E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;; E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;; E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;; E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;; E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;; E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;; E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;; E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;; E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;; E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;; E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;; E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;; E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;; E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;; E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;; E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;; E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;; E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;; E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;; E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;; E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;; E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;; E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;; E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;; E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;; E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;; E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;; E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;; E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;; E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;; E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;; E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;; E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;; E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;; E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;; E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;; E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;; E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;; E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;; E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;; E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;; E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;; E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;; E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;; E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;; E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;; E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;; E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;; E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;; E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;; E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;; E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;; E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;; E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;; E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;; E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;; E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;; E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;; E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;; E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;; E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;; E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;; E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;; E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;; E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;; E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;; E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;; E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;; E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;; E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;; E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;; E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;; E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;; E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;; E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;; E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;; E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;; E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;; E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;; E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;; E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;; E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;; E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;; E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;; E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;; E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;; E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;; E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;; E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;; E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;; E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;; E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;; E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;; E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;; E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;; E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;; E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;; E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;; E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;; E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;; E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;; E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;; E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;; E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;; E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;; E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;; F0000;;Co;0;L;;;;;N;;;;; FFFFD;;Co;0;L;;;;;N;;;;; 100000;;Co;0;L;;;;;N;;;;; 10FFFD;;Co;0;L;;;;;N;;;;; elixir-lang-1.1.0~0.20150708/lib/elixir/unicode/unicode.ex000066400000000000000000000237131254730255300225770ustar00rootroot00000000000000defmodule String.Unicode do @moduledoc false def version, do: {7, 0, 0} to_binary = fn "" -> nil codepoints -> codepoints = :binary.split(codepoints, " ", [:global]) Enum.reduce codepoints, "", fn(codepoint, acc) -> acc <> << String.to_integer(codepoint, 16) :: utf8 >> end end data_path = Path.join(__DIR__, "UnicodeData.txt") {codes, whitespace} = Enum.reduce File.stream!(data_path), {[], []}, fn(line, {cacc, wacc}) -> [codepoint, _name, _category, _class, bidi, _decomposition, _numeric_1, _numeric_2, _numeric_3, _bidi_mirror, _unicode_1, _iso, upper, lower, title] = :binary.split(line, ";", [:global]) title = :binary.part(title, 0, byte_size(title) - 1) cond do upper != "" or lower != "" or title != "" -> {[{to_binary.(codepoint), to_binary.(upper), to_binary.(lower), to_binary.(title)} | cacc], wacc} bidi in ["B", "S", "WS"] -> {cacc, [to_binary.(codepoint) | wacc]} true -> {cacc, wacc} end end special_path = Path.join(__DIR__, "SpecialCasing.txt") codes = Enum.reduce File.stream!(special_path), codes, fn(line, acc) -> [codepoint, lower, title, upper, _comment] = :binary.split(line, "; ", [:global]) key = to_binary.(codepoint) :lists.keystore(key, 1, acc, {key, to_binary.(upper), to_binary.(lower), to_binary.(title)}) end # Downcase def downcase(string), do: downcase(string, "") for {codepoint, _upper, lower, _title} <- codes, lower && lower != codepoint do defp downcase(unquote(codepoint) <> rest, acc) do downcase(rest, acc <> unquote(lower)) end end defp downcase(<>, acc) do downcase(rest, <>) end defp downcase("", acc), do: acc # Upcase def upcase(string), do: upcase(string, "") for {codepoint, upper, _lower, _title} <- codes, upper && upper != codepoint do defp upcase(unquote(codepoint) <> rest, acc) do upcase(rest, acc <> unquote(upper)) end end defp upcase(<>, acc) do upcase(rest, <>) end defp upcase("", acc), do: acc # Titlecase once def titlecase_once(""), do: {"", ""} for {codepoint, _upper, _lower, title} <- codes, title && title != codepoint do def titlecase_once(unquote(codepoint) <> rest) do {unquote(title), rest} end end def titlecase_once(<< char, rest :: binary >>) do {<< char >>, rest} end # Strip def lstrip(string) def lstrip(""), do: "" for codepoint <- whitespace do def lstrip(unquote(codepoint) <> rest) do lstrip(rest) end end def lstrip(string) when is_binary(string), do: string @whitespace_max_size 3 for codepoint <- whitespace do # We need to increment @whitespace_max_size as well # as the small table (_s) if we add a new entry here. case byte_size(codepoint) do 3 -> defp do_rstrip_l(unquote(codepoint)), do: -3 2 -> defp do_rstrip_l(<<_, unquote(codepoint)>>), do: -2 defp do_rstrip_s(unquote(codepoint)), do: <<>> 1 -> defp do_rstrip_l(<>), do: -3 defp do_rstrip_l(<<_, unquote(codepoint), unquote(codepoint)>>), do: -2 defp do_rstrip_l(<<_, _, unquote(codepoint)>>), do: -1 defp do_rstrip_s(<>), do: do_rstrip_s(<>) defp do_rstrip_s(unquote(codepoint)), do: <<>> end end defp do_rstrip_l(_), do: 0 defp do_rstrip_s(o), do: o def rstrip(string) when is_binary(string) do rstrip(string, byte_size(string)) end defp rstrip(string, size) when size < @whitespace_max_size do do_rstrip_s(string) end defp rstrip(string, size) do trail = binary_part(string, size, -@whitespace_max_size) case do_rstrip_l(trail) do 0 -> string x -> rstrip(binary_part(string, 0, size + x), size + x) end end # Split def split(""), do: [] def split(string) when is_binary(string) do :lists.reverse do_split(string, "", []) end for codepoint <- whitespace do defp do_split(unquote(codepoint) <> rest, buffer, acc) do do_split(rest, "", add_buffer_to_acc(buffer, acc)) end end defp do_split(<< char, rest :: binary >>, buffer, acc) do do_split(rest, << buffer :: binary, char >>, acc) end defp do_split(<<>>, buffer, acc) do add_buffer_to_acc(buffer, acc) end @compile {:inline, add_buffer_to_acc: 2} defp add_buffer_to_acc("", acc), do: acc defp add_buffer_to_acc(buffer, acc), do: [buffer|acc] # Codepoints def next_codepoint(<< cp :: utf8, rest :: binary >>) do {<>, rest} end def next_codepoint(<< cp, rest :: binary >>) do {<>, rest} end def next_codepoint(<<>>) do nil end def codepoints(binary) when is_binary(binary) do do_codepoints(next_codepoint(binary)) end defp do_codepoints({c, rest}) do [c|do_codepoints(next_codepoint(rest))] end defp do_codepoints(nil) do [] end end defmodule String.Graphemes do @moduledoc false cluster_path = Path.join(__DIR__, "GraphemeBreakProperty.txt") regex = ~r/(?:^([0-9A-F]+)(?:\.\.([0-9A-F]+))?)\s+;\s(\w+)/m to_range = fn first, "" -> [<< String.to_integer(first, 16) :: utf8 >>] first, last -> range = String.to_integer(first, 16)..String.to_integer(last, 16) Enum.map(range, fn(int) -> << int :: utf8 >> end) end cluster = Enum.reduce File.stream!(cluster_path), HashDict.new, fn(line, dict) -> [_full, first, last, class] = Regex.run(regex, line) # Skip surrogates if first == "D800" and last == "DFFF" do dict else list = to_range.(first, last) Dict.update(dict, class, list, &(&1 ++ list)) end end # There is no codepoint marked as Prepend by Unicode 6.3.0 if cluster["Prepend"] do raise "It seems this new unicode version has added Prepend items. " <> "Please remove this error and uncomment the code below." end # Don't break CRLF def next_grapheme(<< ?\r, ?\n, rest :: binary >>) do {"\r\n", rest} end # Break on control for codepoint <- cluster["CR"] ++ cluster["LF"] ++ cluster["Control"] do def next_grapheme(<< unquote(codepoint), rest :: binary >> = string) do {:binary.part(string, 0, unquote(byte_size(codepoint))), rest} end end # Break on Prepend* # for codepoint <- cluster["Prepend"] do # def next_grapheme(<< unquote(codepoint), rest :: binary >> = string) do # next_prepend(rest, string, unquote(byte_size(codepoint))) # end # end # Handle Hangul L for codepoint <- cluster["L"] do def next_grapheme(<< unquote(codepoint), rest :: binary >> = string) do next_hangul_l(rest, string, unquote(byte_size(codepoint))) end end # Handle Hangul T for codepoint <- cluster["T"] do def next_grapheme(<< unquote(codepoint), rest :: binary >> = string) do next_hangul_t(rest, string, unquote(byte_size(codepoint))) end end # Handle Regional for codepoint <- cluster["Regional_Indicator"] do def next_grapheme(<< unquote(codepoint), rest :: binary >> = string) do next_regional(rest, string, unquote(byte_size(codepoint))) end end # Handle extended entries def next_grapheme(<< cp :: utf8, rest :: binary >> = string) do next_extend(rest, string, byte_size(<< cp :: utf8 >>)) end def next_grapheme(<< cp, rest :: binary >>) do {<>, rest} end def next_grapheme(<<>>) do nil end # Handle Hangul L for codepoint <- cluster["L"] do defp next_hangul_l(<< unquote(codepoint), rest :: binary >>, string, size) do next_hangul_l(rest, string, size + unquote(byte_size(codepoint))) end end for codepoint <- cluster["LV"] do defp next_hangul_l(<< unquote(codepoint), rest :: binary >>, string, size) do next_hangul_v(rest, string, size + unquote(byte_size(codepoint))) end end for codepoint <- cluster["LVT"] do defp next_hangul_l(<< unquote(codepoint), rest :: binary >>, string, size) do next_hangul_t(rest, string, size + unquote(byte_size(codepoint))) end end defp next_hangul_l(rest, string, size) do next_hangul_v(rest, string, size) end # Handle Hangul V for codepoint <- cluster["V"] do defp next_hangul_v(<< unquote(codepoint), rest :: binary >>, string, size) do next_hangul_v(rest, string, size + unquote(byte_size(codepoint))) end end defp next_hangul_v(rest, string, size) do next_hangul_t(rest, string, size) end # Handle Hangul T for codepoint <- cluster["T"] do defp next_hangul_t(<< unquote(codepoint), rest :: binary >>, string, size) do next_hangul_t(rest, string, size + unquote(byte_size(codepoint))) end end defp next_hangul_t(rest, string, size) do next_extend(rest, string, size) end # Handle regional for codepoint <- cluster["Regional_Indicator"] do defp next_regional(<< unquote(codepoint), rest :: binary >>, string, size) do next_regional(rest, string, size + unquote(byte_size(codepoint))) end end defp next_regional(rest, string, size) do next_extend(rest, string, size) end # Handle Extend+SpacingMark for codepoint <- cluster["Extend"] ++ cluster["SpacingMark"] do defp next_extend(<< unquote(codepoint), rest :: binary >>, string, size) do next_extend(rest, string, size + unquote(byte_size(codepoint))) end end defp next_extend(rest, string, size) do {:binary.part(string, 0, size), rest} end # Handle Prepend # for codepoint <- cluster["Prepend"] do # defp next_prepend(<< unquote(codepoint), rest :: binary >>, string, size) do # next_prepend(rest, string, size + unquote(byte_size(codepoint))) # end # end # # defp next_prepend(rest, string, size) do # {:binary.part(string, 0, size), rest} # end def graphemes(binary) when is_binary(binary) do do_graphemes(next_grapheme(binary)) end defp do_graphemes({c, rest}) do [c|do_graphemes(next_grapheme(rest))] end defp do_graphemes(nil) do [] end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/000077500000000000000000000000001254730255300173365ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/examples/000077500000000000000000000000001254730255300211545ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/examples/one_of_each.exs000066400000000000000000000065141254730255300241300ustar00rootroot00000000000000ExUnit.start [seed: 0] defmodule TestOneOfEach do @moduledoc """ This module contains one of each type of failing test. It is used simply to document the style of each. """ use ExUnit.Case, async: false @one 1 @two 2 @long_data_1 [ field1: "one", field2: {:two1, :two2}, field3: 'three', field4: [1, 2, 3, 4]] @long_data_2 [ field1: "one", field2: {:two1, :two3}, field3: 'three', field4: [1, 2, 3, 4]] test "1. assert with a match" do assert [@one] = [@two] end test "2. assert with a binary operator" do assert @one * 4 > @two *3 end test "3. assert match with a long argument" do assert @long_data_1 = @long_data_2 end test "4. assert equality with a long argument" do assert @long_data_1 == @long_data_2 end test "5. refute with a match" do refute [@one] = [@one] end test "6. refute with a binary operator" do refute @one * 6 > @two *2 end test "7. refute match with a long argument" do refute @long_data_1 = @long_data_1 end test "8. refute equality with a long argument" do refute @long_data_1 == @long_data_1 end test "9. assert of an expression with a message" do assert 1 > 2, "is one greater than two?" end test "10. assert with explicit expected and actual values" do assert @one > @two, @one, @two, "one should be greater than two" end test "11. assert that a message is ready to be received" do assert_received :no_message_there end test "12. assert that a message is received within a timeout" do assert_receive :no_message_after_timeout end test "13. assert an exception with a given message is raised, but no exception" do assert_raise(SomeException, "some message", fn -> end) end test "14. assert an exception with a given message is raised" do assert_raise(SomeException, "some message", fn -> raise "other exception" end) end test "15. assert an exception with a given message is raised, but the message is wrong" do assert_raise(RuntimeError, "some message", fn -> raise "other error" end) end test "16. assert an exception is raised" do assert_raise(SomeException, fn -> end) end test "17. assert two values are within some delta" do assert_in_delta 3.1415926, 22.0/7, 0.001 end test "18. refute a value with a message" do refute @one != @two, "one should equal two" end test "19. refute a message is received within a timeout" do send self, {:hello, "Dave"} refute_receive {:hello, _}, 1000 end test "20. refute a message is ready to be received" do send self, :hello_again refute_received :hello_again end test "21. refute two values are within delta" do refute_in_delta @one, @two, 1.5 end test "22. refute two values are within delta with message" do refute_in_delta @one, @two, 1.5, "they shouldn't be this close" end test "23. flunk" do flunk "we failed. totally" end test "24. exception raised while running test" do assert blows_up end test "25. error due to exit" do spawn_link fn -> raise "oops" end receive do end end defp blows_up do ignite(0) + 1 end defp ignite(val) do 1/val end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/000077500000000000000000000000001254730255300201045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit.ex000066400000000000000000000143701254730255300221220ustar00rootroot00000000000000defmodule ExUnit do @moduledoc """ Basic unit testing framework for Elixir. ## Example A basic setup for ExUnit is shown below: # File: assertion_test.exs # 1) Start ExUnit. ExUnit.start # 2) Create a new test module (test case) and use `ExUnit.Case`. defmodule AssertionTest do # 3) Notice we pass `async: true`, this runs the test case # concurrently with other test cases use ExUnit.Case, async: true # 4) Use the `test` macro instead of `def` for clarity. test "the truth" do assert true end end To run the tests above, run the file using `elixir` from the command line. Assuming you named the file `assertion_test.exs`, you can run it as: elixir assertion_test.exs ## Case, Callbacks and Assertions See `ExUnit.Case` and `ExUnit.Callbacks` for more information about defining test cases. The `ExUnit.Assertions` module contains a set of macros to easily generate assertions with appropriate error messages. ## Integration with Mix Mix is the project management and build tool for Elixir. Invoking `mix test` from the command line will run the tests in each file matching the pattern `*_test.exs` found in the `test` directory of your project. You must create a `test_helper.exs` file inside the `test` directory and put the code common to all tests there. The minimum example of a `test_helper.exs` file would be: # test/test_helper.exs ExUnit.start Mix will load the `test_helper.exs` file before executing the tests. It is not necessary to `require` the `test_helper.exs` file in your test files. See `Mix.Tasks.Test` for more information. """ @typedoc "The state returned by ExUnit.Test and ExUnit.TestCase" @type state :: nil | {:failed, failed} | {:skip, binary} | {:invalid, module} @type failed :: {Exception.kind, reason :: term, stacktrace :: [tuple]} defmodule Test do @moduledoc """ A struct that keeps information about the test. It is received by formatters and contains the following fields: * `:name` - the test name * `:case` - the test case * `:state` - the test state (see ExUnit.state) * `:time` - the time to run the test * `:tags` - the test tags * `:logs` - the captured logs """ defstruct [:name, :case, :state, time: 0, tags: %{}, logs: ""] @type t :: %__MODULE__{ name: atom, case: module, state: ExUnit.state, time: non_neg_integer, tags: map} end defmodule TestCase do @moduledoc """ A struct that keeps information about the test case. It is received by formatters and contains the following fields: * `:name` - the test case name * `:state` - the test state (see ExUnit.state) * `:tests` - all tests for this case """ defstruct name: nil, state: nil, tests: [] @type t :: %__MODULE__{ name: module, state: ExUnit.state, tests: [ExUnit.Test.t]} end defmodule TimeoutError do defexception [:timeout] def message(timeout) def message(%{timeout: timeout}) do "test timed out after #{timeout}ms. You can change the timeout globally " <> "via ExUnit.start/1 or per test by setting \"@tag timeout: x\" where x " <> "is an integer in milliseconds)" end end use Application @doc false def start(_type, []) do import Supervisor.Spec children = [ worker(ExUnit.Server, []), worker(ExUnit.OnExitHandler, []) ] opts = [strategy: :one_for_one, name: ExUnit.Supervisor] Supervisor.start_link(children, opts) end @doc """ Starts ExUnit and automatically runs tests right before the VM terminates. It accepts a set of options to configure `ExUnit` (the same ones accepted by `configure/1`). If you want to run tests manually, you can set `:autorun` to `false`. """ def start(options \\ []) do {:ok, _} = Application.ensure_all_started(:ex_unit) configure(options) if Application.get_env(:ex_unit, :autorun, true) do Application.put_env(:ex_unit, :autorun, false) System.at_exit fn 0 -> %{failures: failures} = ExUnit.run System.at_exit fn _ -> if failures > 0, do: exit({:shutdown, 1}) end _ -> :ok end end end @doc """ Configures ExUnit. ## Options ExUnit supports the following options: * `:assert_receive_timeout` - the timeout to be used on `assert_receive` calls. Defaults to 100ms. * `:colors` - a keyword list of colors to be used by some formatters. The only option so far is `[enabled: boolean]` which defaults to `IO.ANSI.enabled?/0` * `:formatters` - the formatters that will print results; defaults to `[ExUnit.CLIFormatter]` * `:max_cases` - maximum number of cases to run in parallel; defaults to `:erlang.system_info(:schedulers_online)` * `:trace` - set ExUnit into trace mode, this sets `:max_cases` to `1` and prints each test case and test while running * `:autorun` - if ExUnit should run by default on exit; defaults to `true` * `:include` - specify which tests are run by skipping tests that do not match the filter * `:exclude` - specify which tests are run by skipping tests that match the filter * `:refute_receive_timeout` - the timeout to be used on `refute_receive` calls. Defaults to 100ms. * `:seed` - an integer seed value to randomize the test suite * `:timeout` - set the timeout for the tests (default 60_000 ms) """ def configure(options) do Enum.each options, fn {k, v} -> Application.put_env(:ex_unit, k, v) end end @doc """ Returns ExUnit configuration. """ def configuration do Application.get_all_env(:ex_unit) end @doc """ API used to run the tests. It is invoked automatically if ExUnit is started via `ExUnit.start/1`. Returns a map containing the total number of tests, the number of failures and the number of skipped tests. """ def run do {async, sync, load_us} = ExUnit.Server.start_run ExUnit.Runner.run async, sync, configuration, load_us end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/000077500000000000000000000000001254730255300215575ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/assertions.ex000066400000000000000000000321441254730255300243130ustar00rootroot00000000000000defmodule ExUnit.AssertionError do @no_value :ex_unit_no_meaningful_value defexception left: @no_value, right: @no_value, message: @no_value, expr: @no_value @doc """ Indicates no meaningful value for a field. """ def no_value do @no_value end end defmodule ExUnit.Assertions do @moduledoc """ This module contains a set of assertion functions that are imported by default into your test cases. In general, a developer will want to use the general `assert` macro in tests. This macro tries to be smart and provide good reporting whenever there is a failure. For example, `assert some_fun() == 10` will fail (assuming `some_fun()` returns 13): Comparison (using ==) failed in: code: some_fun() == 10 lhs: 13 rhs: 10 This module also provides other convenience functions like `assert_in_delta` and `assert_raise` to easily handle other common cases such as checking a floating point number or handling exceptions. """ @doc """ Asserts its argument is `true`. `assert` tries to be smart and provide good reporting whenever there is a failure. In particular, if given a match expression, it will report any failure in terms of that match. Given assert [one] = [two] you'll see: match (=) failed code: [one] = [two] rhs: [2] If the expression is a comparison operator, the message will show the values of the two sides. The assertion assert 1+2+3+4 > 15 will fail with the message: Assertion with > failed code: 1+2+3+4 > 15 lhs: 10 rhs: 15 """ defmacro assert({:=, _, [left, right]} = assertion) do code = Macro.escape(assertion) {:case, meta, args} = quote do case right do unquote(left) -> right _ -> raise ExUnit.AssertionError, right: right, expr: unquote(code), message: "match (=) failed" end end quote do right = unquote(right) unquote({:case, [{:export_head, true}|meta], args}) end end defmacro assert(assertion) do case translate_assertion(assertion) do nil -> quote do value = unquote(assertion) unless value do raise ExUnit.AssertionError, expr: unquote(Macro.escape(assertion)), message: "Expected truthy, got #{inspect value}" end value end value -> value end end @doc """ This is a negative assertion, failing if its parameter is truthy. ## Examples refute age < 0 """ defmacro refute({:=, _, [left, right]} = assertion) do code = Macro.escape(assertion) {:case, meta, args} = quote do case right do unquote(left) -> raise ExUnit.AssertionError, right: right, expr: unquote(code), message: "match (=) succeeded, but should have failed" _ -> right end end quote do right = unquote(right) unquote({:case, [{:export_head, true}|meta], args}) end end defmacro refute(assertion) do case translate_assertion({:!, [], [assertion]}) do nil -> quote do value = unquote(assertion) if value do raise ExUnit.AssertionError, expr: unquote(Macro.escape(assertion)), message: "Expected false or nil, got #{inspect value}" end value end value -> {:!, [], [value]} end end ## START HELPERS @operator [:==, :<, :>, :<=, :>=, :===, :=~, :!==, :!=, :in] defp translate_assertion({operator, _, [left, right]} = expr) when operator in @operator do expr = Macro.escape(expr) quote do left = unquote(left) right = unquote(right) assert unquote(operator)(left, right), left: left, right: right, expr: unquote(expr), message: unquote("Assertion with #{operator} failed") end end defp translate_assertion({:!, [], [{operator, _, [left, right]} = expr]}) when operator in @operator do expr = Macro.escape(expr) quote do left = unquote(left) right = unquote(right) assert not(unquote(operator)(left, right)), left: left, right: right, expr: unquote(expr), message: unquote("Refute with #{operator} failed") end end defp translate_assertion(_expected) do nil end ## END HELPERS @doc """ Asserts `value` is `true`, displaying the given `message` otherwise. ## Examples assert false, "it will never be true" """ def assert(value, message) when is_binary(message) do assert(value, message: message) end def assert(value, opts) when is_list(opts) do unless value, do: raise(ExUnit.AssertionError, opts) true end @doc """ Asserts a message was or is going to be received. Unlike `assert_received`, it has a default timeout of 100 milliseconds. The `expected` argument is a pattern. ## Examples assert_receive :hello Asserts against a larger timeout: assert_receive :hello, 20_000 You can also match against specific patterns: assert_receive {:hello, _} x = 5 assert_receive {:count, ^x} """ defmacro assert_receive(expected, timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout), message \\ nil) do do_assert_receive(expected, timeout, message) end @doc """ Asserts a message was received and is in the current process' mailbox. Timeout is set to 0, so there is no waiting time. The `expected` argument is a pattern. ## Examples send self, :hello assert_received :hello You can also match against specific patterns: send self, {:hello, "world"} assert_received {:hello, _} """ defmacro assert_received(expected, message \\ nil) do do_assert_receive(expected, 0, message) end defp do_assert_receive(expected, timeout, message) do binary = Macro.to_string(expected) pattern = case expected do {:when, meta, [left, right]} -> {:when, meta, [quote(do: unquote(left) = received), right]} left -> quote(do: unquote(left) = received) end {:receive, meta, args} = quote do receive do unquote(pattern) -> received after timeout -> message = unquote(message) || "No message matching #{unquote(binary)} after #{timeout}ms" flunk(message <> ExUnit.Assertions.__mailbox__(self())) end end quote do timeout = unquote(timeout) unquote({:receive, [{:export_head, true}|meta], args}) end end @max_mailbox_length 10 @doc false def __mailbox__(pid) do {:messages, messages} = Process.info(pid, :messages) length = length(messages) mailbox = Enum.take(messages, @max_mailbox_length) |> Enum.map_join("\n", &inspect/1) mailbox_message(length, mailbox) end defp mailbox_message(0, _mailbox), do: ". The process mailbox is empty." defp mailbox_message(length, mailbox) when length > 10 do ". Process mailbox:\n" <> mailbox <> "\nShowing only #{@max_mailbox_length} of #{length} messages." end defp mailbox_message(_length, mailbox) do ". Process mailbox:\n" <> mailbox end @doc """ Asserts the `exception` is raised during `function` execution with the `expected_message`. Returns the rescued exception, fails otherwise. ## Examples assert_raise ArithmeticError, "bad argument in arithmetic expression", fn -> 1 + "test" end """ def assert_raise(exception, message, function) when is_function(function) do error = assert_raise(exception, function) is_match = cond do is_binary(message) -> Exception.message(error) == message Regex.regex?(message) -> Exception.message(error) =~ message end msg = "Wrong message for #{inspect exception}. " <> "Expected #{inspect message}, got #{inspect Exception.message(error)}" assert is_match, message: msg error end @doc """ Asserts the `exception` is raised during `function` execution. Returns the rescued exception, fails otherwise. ## Examples assert_raise ArithmeticError, fn -> 1 + "test" end """ def assert_raise(exception, function) when is_function(function) do try do function.() rescue error -> stacktrace = System.stacktrace name = error.__struct__ cond do name == exception -> error name == ExUnit.AssertionError -> reraise(error, stacktrace) true -> flunk "Expected exception #{inspect exception} but got #{inspect name} (#{Exception.message(error)})" end else _ -> flunk "Expected exception #{inspect exception} but nothing was raised" end end @doc """ Asserts that `value1` and `value2` differ by no more than `delta`. ## Examples assert_in_delta 1.1, 1.5, 0.2 assert_in_delta 10, 15, 4 """ def assert_in_delta(value1, value2, delta, message \\ nil) do diff = abs(value1 - value2) message = message || "Expected the difference between #{inspect value1} and " <> "#{inspect value2} (#{inspect diff}) to be less than #{inspect delta}" assert diff < delta, message end @doc """ Asserts `expression` will throw a value. Returns the thrown value or fails otherwise. ## Examples assert catch_throw(throw 1) == 1 """ defmacro catch_throw(expression) do do_catch(:throw, expression) end @doc """ Asserts `expression` will exit. Returns the exit status/message or fails otherwise. ## Examples assert catch_exit(exit 1) == 1 """ defmacro catch_exit(expression) do do_catch(:exit, expression) end @doc """ Asserts `expression` will cause an error. Returns the error or fails otherwise. ## Examples assert catch_error(error 1) == 1 """ defmacro catch_error(expression) do do_catch(:error, expression) end defp do_catch(kind, expr) do quote do try do unquote(expr) flunk "Expected to catch #{unquote(kind)}, got nothing" rescue e in [ExUnit.AssertionError] -> reraise(e, System.stacktrace) catch unquote(kind), we_got -> we_got end end end @doc """ Asserts `value` is `nil` or `false` (that is, `value` is not truthy). ## Examples refute true, "This will obviously fail" """ def refute(value, message) do not assert(!value, message) end @doc """ Asserts `message` was not received (and won't be received) within the `timeout` period. The `not_expected` argument is a match pattern. ## Examples refute_receive :bye Refute received with a explicit timeout: refute_receive :bye, 1000 """ defmacro refute_receive(not_expected, timeout \\ Application.fetch_env!(:ex_unit, :refute_receive_timeout), message \\ nil) do do_refute_receive(not_expected, timeout, message) end @doc """ Asserts a message was not received (i.e. it is not in the current process mailbox). The `not_expected` argument must be a match pattern. Timeout is set to 0, so there is no waiting time. ## Examples send self, :hello refute_received :bye """ defmacro refute_received(not_expected, message \\ nil) do do_refute_receive(not_expected, 0, message) end defp do_refute_receive(not_expected, timeout, message) do receive_clause = refute_receive_clause(not_expected, message) quote do receive do unquote(receive_clause) after unquote(timeout) -> false end end end defp refute_receive_clause(not_expected, nil) do binary = Macro.to_string(not_expected) quote do unquote(not_expected) = actual -> flunk "Unexpectedly received message #{inspect actual} (which matched #{unquote binary})" end end defp refute_receive_clause(not_expected, message) do quote do unquote(not_expected) -> flunk unquote(message) end end @doc """ Asserts `value1` and `value2` are not within `delta`. If you supply `message`, information about the values will automatically be appended to it. ## Examples refute_in_delta 1.1, 1.2, 0.2 refute_in_delta 10, 11, 2 """ def refute_in_delta(value1, value2, delta, message \\ nil) do diff = abs(value1 - value2) message = if message do message <> " (difference between #{inspect value1} " <> "and #{inspect value2} is less than #{inspect delta})" else "Expected the difference between #{inspect value1} and " <> "#{inspect value2} (#{inspect diff}) to be more than #{inspect delta}" end refute diff < delta, message end @doc """ Fails with a message. ## Examples flunk "This should raise an error" """ @spec flunk :: no_return @spec flunk(String.t) :: no_return def flunk(message \\ "Flunked!") when is_binary(message) do assert false, message: message end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/callbacks.ex000066400000000000000000000134531254730255300240420ustar00rootroot00000000000000defmodule ExUnit.Callbacks do @moduledoc ~S""" Defines ExUnit Callbacks. This module defines both `setup_all` and `setup` callbacks, as well as the `on_exit` facility. The setup callbacks are defined via macros and each one can optionally receive a map with metadata, usually referred to as `context`. The callback may optionally put extra data into `context` to be used in the tests. The `setup_all` callbacks are invoked once to setup the test case before any test is run and all `setup` callbacks are run before each test. No callback runs if the test case has no tests or all tests were filtered out. `on_exit` callbacks are registered on demand, usually to undo an action performed by a setup callback. `on_exit` may also take a reference, allowing callback to be overridden in the future. A registered `on_exit` callback always runs, while failures in `setup` and `setup_all` will stop all remaining setup callbacks from executing. Finally, `setup_all` callbacks run in the test case process, while all `setup` callbacks run in the same process as the test itself. `on_exit` callbacks always run in a separate process than the test case or the test itself. Since the test process exits with reason `:shutdown`, most of times `on_exit/1` can be avoided as processes are going to clean up on their own. ## Context If you return `{:ok, }` from `setup_all`, the dictionary will be merged into the current context and be available in all subsequent `setup_all`, `setup` and the test itself. Similarly, returning `{:ok, }` from `setup`, the dict returned will be merged into the current context and be available in all subsequent `setup` and the `test` itself. Returning `:ok` leaves the context unchanged in both cases. Returning anything else from `setup_all` will force all tests to fail, while a bad response from `setup` causes the current test to fail. ## Examples defmodule AssertionTest do use ExUnit.Case, async: true # `setup_all` is called once to setup the case before any test is run setup_all do IO.puts "Starting AssertionTest" # No metadata :ok end # `setup` is called before each test is run setup do IO.puts "This is a setup callback" on_exit fn -> IO.puts "This is invoked once the test is done" end # Returns extra metadata, it must be a dict {:ok, hello: "world"} end # Same as `setup`, but receives the context # for the current test setup context do IO.puts "Setting up: #{context[:test]}" :ok end test "always pass" do assert true end test "another one", context do assert context[:hello] == "world" end end """ @doc false defmacro __using__(_) do quote do @ex_unit_setup [] @ex_unit_setup_all [] @before_compile unquote(__MODULE__) import unquote(__MODULE__) end end @doc false defmacro __before_compile__(env) do [compile_callbacks(env, :setup), compile_callbacks(env, :setup_all)] end @doc """ Defines a callback to be run before each test in a case. """ defmacro setup(var \\ quote(do: _), block) do quote bind_quoted: [var: escape(var), block: escape(block)] do name = :"__ex_unit_setup_#{length(@ex_unit_setup)}" defp unquote(name)(unquote(var)), unquote(block) @ex_unit_setup [name|@ex_unit_setup] end end @doc """ Defines a callback to be run before all tests in a case. """ defmacro setup_all(var \\ quote(do: _), block) do quote bind_quoted: [var: escape(var), block: escape(block)] do name = :"__ex_unit_setup_all_#{length(@ex_unit_setup_all)}" defp unquote(name)(unquote(var)), unquote(block) @ex_unit_setup_all [name|@ex_unit_setup_all] end end @doc """ Defines a callback that runs on the test (or test case) exit. An `on_exit` callback is a function that receives no arguments and runs in a separate process than the caller. `on_exit/2` is usually called from `setup` and `setup_all` callbacks, often to undo the action performed during `setup`. However, `on_exit` may also be called dynamically, where a reference can be used to guarantee the callback will be invoked only once. """ @spec on_exit(term, (() -> term)) :: :ok def on_exit(ref \\ make_ref, callback) do case ExUnit.OnExitHandler.add(self, ref, callback) do :ok -> :ok :error -> raise ArgumentError, "on_exit/1 callback can only be invoked from the test process" end end ## Helpers @doc false def __merge__(_mod, other, :ok) do {:ok, other} end def __merge__(_mod, other, {:ok, data}) do {:ok, Dict.merge(other, data)} end def __merge__(mod, _, failure) do raise "expected ExUnit callback in #{inspect mod} to return :ok " <> " or {:ok, dict}, got #{inspect failure} instead" end defp escape(contents) do Macro.escape(contents, unquote: true) end defp compile_callbacks(env, kind) do callbacks = Module.get_attribute(env.module, :"ex_unit_#{kind}") |> Enum.reverse acc = case callbacks do [] -> quote do: {:ok, context} [h|t] -> Enum.reduce t, compile_merge(h), fn(callback, acc) -> quote do case unquote(acc) do {:ok, context} -> unquote(compile_merge(callback)) other -> other end end end end quote do def __ex_unit__(unquote(kind), context), do: unquote(acc) end end defp compile_merge(callback) do quote do unquote(__MODULE__).__merge__(__MODULE__, context, unquote(callback)(context)) end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/capture_io.ex000066400000000000000000000100731254730255300242500ustar00rootroot00000000000000defmodule ExUnit.CaptureIO do @moduledoc ~S""" Functionality to capture IO for testing. ## Examples defmodule AssertionTest do use ExUnit.Case import ExUnit.CaptureIO test :example do assert capture_io(fn -> IO.puts "a" end) == "a\n" end test "checking the return value and the IO output" do fun = fn -> assert Enum.each(["some", "example"], &(IO.puts &1)) == :ok end assert capture_io(fun) == "some\nexample\n" # tip: or use only: `capture_io(fun)` to silence the IO output (so only assert the return value) end end """ @doc """ Captures IO generated when evaluating `fun`. Returns the binary which is the captured output. By default, `capture_io` replaces the `group_leader` (`:stdio`) for the current process. However, the capturing of any other named device, such as `:stderr`, is also possible globally by giving the registered device name explicitly as an argument. Note that when capturing something other than `:stdio`, the test should run with async false. When capturing `:stdio`, if the `:capture_prompt` option is `false`, prompts (specified as arguments to `IO.get*` functions) are not captured. A developer can set a string as an input. The default input is `:eof`. ## Examples iex> capture_io(fn -> IO.write "john" end) == "john" true iex> capture_io(:stderr, fn -> IO.write(:stderr, "john") end) == "john" true iex> capture_io("this is input", fn -> ...> input = IO.gets ">" ...> IO.write input ...> end) == ">this is input" true iex> capture_io([input: "this is input", capture_prompt: false], fn -> ...> input = IO.gets ">" ...> IO.write input ...> end) == "this is input" true """ def capture_io(fun) do do_capture_io(:standard_io, [], fun) end def capture_io(device, fun) when is_atom(device) do capture_io(device, [], fun) end def capture_io(input, fun) when is_binary(input) do capture_io(:standard_io, [input: input], fun) end def capture_io(options, fun) when is_list(options) do capture_io(:standard_io, options, fun) end def capture_io(device, input, fun) when is_binary(input) do capture_io(device, [input: input], fun) end def capture_io(device, options, fun) when is_list(options) do do_capture_io(map_dev(device), options, fun) end defp map_dev(:stdio), do: :standard_io defp map_dev(:stderr), do: :standard_error defp map_dev(other), do: other defp do_capture_io(:standard_io, options, fun) do prompt_config = Keyword.get(options, :capture_prompt, true) input = Keyword.get(options, :input, "") original_gl = Process.group_leader() {:ok, capture_gl} = StringIO.open(input, capture_prompt: prompt_config) try do Process.group_leader(self(), capture_gl) do_capture_io(capture_gl, fun) after Process.group_leader(self(), original_gl) end end defp do_capture_io(device, options, fun) do unless original_io = Process.whereis(device) do raise "could not find IO device registered at #{inspect device}" end unless ExUnit.Server.add_device(device) do raise "IO device registered at #{inspect device} is already captured" end input = Keyword.get(options, :input, "") Process.unregister(device) {:ok, capture_io} = StringIO.open(input) Process.register(capture_io, device) try do do_capture_io(capture_io, fun) after try do Process.unregister(device) rescue ArgumentError -> nil end Process.register(original_io, device) ExUnit.Server.remove_device(device) end end defp do_capture_io(string_io, fun) do try do _ = fun.() :ok catch kind, reason -> stack = System.stacktrace() _ = StringIO.close(string_io) :erlang.raise(kind, reason, stack) else :ok -> {:ok, output} = StringIO.close(string_io) elem(output, 1) end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/capture_log.ex000066400000000000000000000057371254730255300244350ustar00rootroot00000000000000defmodule ExUnit.CaptureLog do @moduledoc ~S""" Functionality to capture logs for testing. ## Examples defmodule AssertionTest do use ExUnit.Case import ExUnit.CaptureLog test "example" do assert capture_log(fn -> Logger.error "log msg" end) =~ "log msg" end test "check multiple captures concurrently" do fun = fn -> for msg <- ["hello", "hi"] do assert capture_log(fn -> Logger.error msg end) =~ msg end Logger.debug "testing" end assert capture_log(fun) =~ "hello" assert capture_log(fun) =~ "testing" end end """ alias Logger.Backends.Console @doc """ Captures Logger messages generated when evaluating `fun`. Returns the binary which is the captured output. This function mutes the `:console` backend and captures any log messages sent to Logger. Note that when the `async` is set to `true`, the messages from another test might be captured. It is possible to configure the level to capture with `:level`, which will set the capturing level for the duration of the capture, for instance, if the log level is set to :error any message with the lower level will be ignored. The default level is `nil`, which will capture all messages. The behaviour is undetermined if async tests change Logger level. The format, metadata and colors can be configured with `:format`, `:metadata` and `:colors` respectively. These three options defaults to the `:console` backend configuration parameters. """ @spec capture_log(Keyword.t, (() -> any)) :: String.t def capture_log(opts \\ [], fun) do opts = Keyword.put_new(opts, :level, nil) {:ok, string_io} = StringIO.open("") try do :ok = add_capture(string_io, opts) {:ok, ref} = ExUnit.Server.log_capture_on(self()) try do fun.() after :ok = Logger.flush() :ok = ExUnit.Server.log_capture_off(ref) :ok = remove_capture(string_io) end :ok catch kind, reason -> stack = System.stacktrace() _ = StringIO.close(string_io) :erlang.raise(kind, reason, stack) else :ok -> {:ok, content} = StringIO.close(string_io) elem(content, 1) end end defp add_capture(pid, opts) do GenEvent.add_mon_handler(Logger, {Console, pid}, {pid, opts}) end defp remove_capture(pid) do case GenEvent.remove_handler(Logger, {Console, pid}, nil) do :ok -> receive do {:gen_event_EXIT, {Console, ^pid}, _reason} -> :ok end {:error, :not_found} = error -> mfa = {ExUnit.Capture_log, :remove_capture, [pid]} receive do {:gen_event_EXIT, {Console, ^pid}, reason} -> exit({reason, mfa}) after # In case someone accidentally flushed the message, # let's raise not found. 0 -> exit({error, mfa}) end end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/case.ex000066400000000000000000000177261254730255300230450ustar00rootroot00000000000000defmodule ExUnit.Case do @moduledoc """ Sets up an ExUnit test case. This module must be used in other modules as a way to configure and prepare them for testing. When used, it accepts the following options: * :async - configure Elixir to run that specific test case in parallel with others. Must be used for performance when your test cases do not change any global state. It defaults to `false`. This module automatically includes all callbacks defined in `ExUnit.Callbacks`. See that module's documentation for more information. ## Examples defmodule AssertionTest do # Use the module use ExUnit.Case, async: true # The `test` macro is imported by ExUnit.Case test "always pass" do assert true end end ## Context All tests receive a context as an argument. The context is particularly useful for sharing information between callbacks and tests: defmodule KVTest do use ExUnit.Case setup do {:ok, pid} = KV.start_link {:ok, [pid: pid]} end test "stores key-values", context do assert KV.put(context[:pid], :hello, :world) == :ok assert KV.get(context[:pid], :hello) == :world end end As the context is a map, it can be pattern matched on to extract information: test "stores key-values", %{pid: pid} do assert KV.put(pid, :hello, :world) == :ok assert KV.get(pid, :hello) == :world end ## Tags The context is used to pass information from the callbacks to the test. In order to pass information from the test to the callback, ExUnit provides tags. By tagging a test, the tag value can be accessed in the context, allowing the developer to customize the test. Let's see an example: defmodule FileTest do # Changing directory cannot be async use ExUnit.Case, async: false setup context do # Read the :cd tag value if cd = context[:cd] do prev_cd = File.cwd! File.cd!(cd) on_exit fn -> File.cd!(prev_cd) end end :ok end @tag cd: "fixtures" test "reads utf-8 fixtures" do File.read("hello") end end In the example above, we have defined a tag called `:cd` that is read in the setup callback to configure the working directory the test is going to run on. Tags are also very effective when used with case templates (`ExUnit.CaseTemplate`) allowing callbacks in the case template to customize the test behaviour. Note a tag can be set in two different ways: @tag key: value @tag :key # equivalent to setting @tag key: true If a tag is given more than once, the last value wins. ### Module tags A tag can be set for all tests in a module by setting `@moduletag`: @moduletag :external If the same key is set via `@tag`, the `@tag` value has higher precedence. ### Known tags The following tags are set automatically by ExUnit and are therefore reserved: * `:case` - the test case module * `:test` - the test name * `:line` - the line on which the test was defined * `:file` - the file on which the test was defined The following tags customize how tests behaves: * `:timeout` - customizes the test timeout in milliseconds (defaults to 30000) ## Filters Tags can also be used to identify specific tests, which can then be included or excluded using filters. The most common functionality is to exclude some particular tests from running, which can be done via `ExUnit.configure/1`: # Exclude all external tests from running ExUnit.configure(exclude: [external: true]) From now on, ExUnit will not run any test that has the `external` flag set to `true`. This behaviour can be reversed with the `:include` option which is usually passed through the command line: mix test --include external:true Run `mix help test` for more information on how to run filters via Mix. Another use case for tags and filters is to exclude all tests that have a particular tag by default, regardless of its value, and include only a certain subset: ExUnit.configure(exclude: :os, include: [os: :unix]) Keep in mind that all tests are included by default, so unless they are excluded first, the `include` option has no effect. """ @doc false defmacro __using__(opts) do async = Keyword.get(opts, :async, false) unless Process.whereis(ExUnit.Server) do raise "cannot use ExUnit.Case without starting the ExUnit application, " <> "please call ExUnit.start() or explicitly start the :ex_unit app" end quote do unless Module.get_attribute(__MODULE__, :ex_unit_tests) do Enum.each [:ex_unit_tests, :tag, :moduletag], &Module.register_attribute(__MODULE__, &1, accumulate: true) if unquote(async) do @moduletag async: true ExUnit.Server.add_async_case(__MODULE__) else @moduletag async: false ExUnit.Server.add_sync_case(__MODULE__) end @before_compile ExUnit.Case @ex_unit_test_names HashSet.new use ExUnit.Callbacks end import ExUnit.Callbacks import ExUnit.Assertions import ExUnit.Case import ExUnit.DocTest end end @doc """ Define a test with a string. Provides a convenient macro that allows a test to be defined with a string. This macro automatically inserts the atom `:ok` as the last line of the test. That said, a passing test always returns `:ok`, but, more importantly, it forces Elixir to not tail call optimize the test and therefore avoids hiding lines from the backtrace. ## Examples test "true is equal to true" do assert true == true end """ defmacro test(message, var \\ quote(do: _), contents) do contents = case contents do [do: block] -> quote do unquote(block) :ok end _ -> quote do try(unquote(contents)) :ok end end var = Macro.escape(var) contents = Macro.escape(contents, unquote: true) quote bind_quoted: binding do test = :"test #{message}" ExUnit.Case.__on_definition__(__ENV__, test) def unquote(test)(unquote(var)), do: unquote(contents) end end @doc """ Define a not implemented test with a string. Provides a convenient macro that allows a test to be defined with a string, but not yet implemented. The resulting test will always fail and print "Not yet implemented" error message. The resulting test case is also tagged with :not_implemented. ## Examples test "this will be a test in future" """ defmacro test(message) do quote bind_quoted: binding do test = :"test #{message}" ExUnit.Case.__on_definition__(__ENV__, test, [:not_implemented]) def unquote(test)(_), do: flunk("Not yet implemented") end end @doc false defmacro __before_compile__(_) do quote do def __ex_unit__(:case) do %ExUnit.TestCase{name: __MODULE__, tests: @ex_unit_tests} end end end @doc false def __on_definition__(env, name, tags \\ []) do mod = env.module tags = tags ++ Module.get_attribute(mod, :tag) ++ Module.get_attribute(mod, :moduletag) tags = tags |> normalize_tags |> Map.merge(%{line: env.line, file: env.file}) test = %ExUnit.Test{name: name, case: mod, tags: tags} test_names = Module.get_attribute(mod, :ex_unit_test_names) unless name in test_names do Module.put_attribute(mod, :ex_unit_tests, test) Module.put_attribute(mod, :ex_unit_test_names, HashSet.put(test_names, name)) end Module.delete_attribute(mod, :tag) end defp normalize_tags(tags) do Enum.reduce Enum.reverse(tags), %{}, fn tag, acc when is_atom(tag) -> Map.put(acc, tag, true) tag, acc when is_list(tag) -> Dict.merge(acc, tag) end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/case_template.ex000066400000000000000000000033741254730255300247320ustar00rootroot00000000000000defmodule ExUnit.CaseTemplate do @moduledoc """ This module allows a developer to define a test case template to be used throughout their tests. This is useful when there are a set of functions that should be shared between tests or a set of setup callbacks. By using this module, the callbacks and assertions available for regular test cases will also be available. ## Example defmodule MyCase do use ExUnit.CaseTemplate setup do IO.puts "This will run before each test that uses this case" end end defmodule MyTest do use MyCase, async: true test "truth" do assert true end end """ @doc false defmacro __using__(_) do quote do use ExUnit.Callbacks import ExUnit.Assertions import unquote(__MODULE__) defmacro __using__(opts) do unquote(__MODULE__).__proxy__(__MODULE__, opts) end defoverridable [__using__: 1] end end @doc false def __proxy__(module, opts) do quote do use ExUnit.Case, unquote(opts) setup_all context do unquote(module).__ex_unit__(:setup_all, context) end setup context do unquote(module).__ex_unit__(:setup, context) end end end @doc """ Allows a developer to customize the using block when the case template is used. ## Example using do quote do alias MyApp.FunModule end end """ defmacro using(var \\ quote(do: _), do: block) do quote location: :keep do defmacro __using__(unquote(var) = opts) do parent = unquote(__MODULE__).__proxy__(__MODULE__, opts) result = unquote(block) {:__block__, [], [parent, result]} end end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/cli_formatter.ex000066400000000000000000000141351254730255300247530ustar00rootroot00000000000000defmodule ExUnit.CLIFormatter do @moduledoc false use GenEvent import ExUnit.Formatter, only: [format_time: 2, format_filters: 2, format_test_failure: 5, format_test_case_failure: 5] ## Callbacks def init(opts) do print_filters(Keyword.take(opts, [:include, :exclude])) config = %{ seed: opts[:seed], trace: opts[:trace], colors: Keyword.put_new(opts[:colors], :enabled, IO.ANSI.enabled?), width: get_terminal_width(), tests_counter: 0, failures_counter: 0, skipped_counter: 0, invalids_counter: 0 } {:ok, config} end def handle_event({:suite_finished, run_us, load_us}, config) do print_suite(config, run_us, load_us) :remove_handler end def handle_event({:test_started, %ExUnit.Test{} = test}, config) do if config.trace, do: IO.write " * #{trace_test_name test}" {:ok, config} end def handle_event({:test_finished, %ExUnit.Test{state: nil} = test}, config) do if config.trace do IO.puts success(trace_test_result(test), config) else IO.write success(".", config) end {:ok, %{config | tests_counter: config.tests_counter + 1}} end def handle_event({:test_finished, %ExUnit.Test{state: {:skip, _}} = test}, config) do if config.trace, do: IO.puts trace_test_skip(test) {:ok, %{config | tests_counter: config.tests_counter + 1, skipped_counter: config.skipped_counter + 1}} end def handle_event({:test_finished, %ExUnit.Test{state: {:invalid, _}} = test}, config) do if config.trace do IO.puts invalid(trace_test_result(test), config) else IO.write invalid("?", config) end {:ok, %{config | tests_counter: config.tests_counter + 1, invalids_counter: config.invalids_counter + 1}} end def handle_event({:test_finished, %ExUnit.Test{state: {:failed, failed}} = test}, config) do if config.trace do IO.puts failure(trace_test_result(test), config) end formatted = format_test_failure(test, failed, config.failures_counter + 1, config.width, &formatter(&1, &2, config)) print_failure(formatted, config) print_logs(test.logs) {:ok, %{config | tests_counter: config.tests_counter + 1, failures_counter: config.failures_counter + 1}} end def handle_event({:case_started, %ExUnit.TestCase{name: name}}, config) do if config.trace do IO.puts("\n#{inspect name}") end {:ok, config} end def handle_event({:case_finished, %ExUnit.TestCase{state: nil}}, config) do {:ok, config} end def handle_event({:case_finished, %ExUnit.TestCase{state: {:failed, failed}} = test_case}, config) do formatted = format_test_case_failure(test_case, failed, config.failures_counter + 1, config.width, &formatter(&1, &2, config)) print_failure(formatted, config) {:ok, %{config | failures_counter: config.failures_counter + 1}} end def handle_event(_, config) do {:ok, config} end ## Tracing defp trace_test_name(%ExUnit.Test{name: name}) do case Atom.to_string(name) do "test " <> rest -> rest rest -> rest end end defp trace_test_time(%ExUnit.Test{time: time}) do "#{format_us(time)}ms" end defp trace_test_result(test) do "\r * #{trace_test_name test} (#{trace_test_time(test)})" end defp trace_test_skip(test) do "\r * #{trace_test_name test} (skipped)" end defp format_us(us) do us = div(us, 10) if us < 10 do "0.0#{us}" else us = div us, 10 "#{div(us, 10)}.#{rem(us, 10)}" end end ## Printing defp print_suite(config, run_us, load_us) do IO.write "\n\n" IO.puts format_time(run_us, load_us) # singular/plural if config.tests_counter == 1 do test_pl = "test" else test_pl = "tests" end if config.failures_counter == 1 do failure_pl = "failure" else failure_pl = "failures" end message = "#{config.tests_counter} #{test_pl}, #{config.failures_counter} #{failure_pl}" if config.skipped_counter > 0 do message = message <> ", #{config.skipped_counter} skipped" end if config.invalids_counter > 0 do message = message <> ", #{config.invalids_counter} invalid" end cond do config.failures_counter > 0 -> IO.puts failure(message, config) config.invalids_counter > 0 -> IO.puts invalid(message, config) true -> IO.puts success(message, config) end IO.puts "\nRandomized with seed #{config.seed}" end defp print_filters([include: [], exclude: []]) do :ok end defp print_filters([include: include, exclude: exclude]) do if include != [], do: IO.puts format_filters(include, :include) if exclude != [], do: IO.puts format_filters(exclude, :exclude) IO.puts("") :ok end defp print_failure(formatted, config) do cond do config.trace -> IO.puts "" true -> IO.puts "\n" end IO.puts formatted end # Color styles defp colorize(escape, string, %{colors: colors}) do enabled = colors[:enabled] [IO.ANSI.format_fragment(escape, enabled), string, IO.ANSI.format_fragment(:reset, enabled)] |> IO.iodata_to_binary end defp success(msg, config) do colorize([:green], msg, config) end defp invalid(msg, config) do colorize([:yellow], msg, config) end defp failure(msg, config) do colorize([:red], msg, config) end defp formatter(:error_info, msg, config), do: colorize([:red], msg, config) defp formatter(:extra_info, msg, config), do: colorize([:cyan], msg, config) defp formatter(:location_info, msg, config), do: colorize([:bright, :black], msg, config) defp formatter(_, msg, _config), do: msg defp get_terminal_width do case :io.columns do {:ok, width} -> max(40, width) _ -> 80 end end defp print_logs(""), do: nil defp print_logs(output) do indent = "\n " output = String.replace(output, "\n", indent) IO.puts([" The following output was logged:", indent | output]) end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/doc_test.ex000066400000000000000000000443451254730255300237330ustar00rootroot00000000000000defmodule ExUnit.DocTest do @moduledoc """ ExUnit.DocTest implements functionality similar to [Python's doctest](http://docs.python.org/2/library/doctest.html). In a nutshell, it allows us to generate tests from the code examples existing in a module/function/macro's documentation. In order to do that, one needs to invoke the `doctest/1` macro from their test case and write their examples according to some guidelines. The syntax for examples is as follows. Every new test starts on a new line, with an `iex>` prefix. Multiline expressions can be employed if the following lines start with either `...>` (recommended) or `iex>` prefix. The expected result should start at the next line after `iex>` or `...>` line(s) and is terminated either by a newline, new `iex>` prefix or end of the string literal. ## Examples Currently, the only way to run doctests is to include them into an ExUnit case with a `doctest` macro: defmodule MyModule.Test do use ExUnit.Case, async: true doctest MyModule end The `doctest` macro is going to loop through all functions and macros defined in `MyModule`, parsing their documentation in search of code examples. A very basic example is: iex> 1+1 2 Expressions on multiple lines are also supported: iex> Enum.map [1, 2, 3], fn(x) -> ...> x * 2 ...> end [2, 4, 6] Multiple results can be checked within the same test: iex> a = 1 1 iex> a + 1 2 If you want to keep any two tests separate, add an empty line between them: iex> a = 1 1 iex> a + 1 # will fail with a "function a/0 undefined" error 2 Similarly to iex you can use numbers in your "prompts": iex(1)> [1+2, ...(1)> 3] [3, 3] This is useful in two use cases: * being able to refer to specific numbered scenarios * copy-pasting examples from an actual iex session We also allow you to select or skip some functions when calling `doctest`. See the documentation for more info. ## Opaque types Some types internal structure are kept hidden and instead show a user-friendly structure when inspecting the value. The idiom in Elixir is to print those data types as `#Name<...>`. Because those values are treated as comments in Elixir code due to the leading `#` sign, they require special care when used in doctests. Imagine you have a map with a HashSet inside which is printed as: %{users: #HashSet<[:foo, :bar]>} If you try to match on such expression, doctest will fail to compile. You have two options to solve this. The first one is to rely on the fact that doctest can compare internal structures as long as they are at the root. So one could write: iex> map = %{users: Enum.into([:foo, :bar], HashSet.new)} iex> map.users #HashSet<[:foo, :bar]> Whenever a doctest starts with "#Name<", doctest will perform a string comparison. For example, the above test will perform the following match: inspect(map.users) == "#HashSet<[:foo, :bar]>" Alternatively, since doctest results are actually evaluated, you can have the HashSet building expression as the doctest result: iex> %{users: Enum.into([:foo, :bar], HashSet.new)} %{users: Enum.into([:foo, :bar], HashSet.new)} The downside of this approach is that the doctest result is not really what users would see in the terminal. ## Exceptions You can also showcase expressions raising an exception, for example: iex(1)> String.to_atom((fn() -> 1 end).()) ** (ArgumentError) argument error What DocTest will be looking for is a line starting with `** (` and it will parse it accordingly to extract the exception name and message. At this moment, the exception parser would make the parser treat the next line as a start of a completely new expression (if it is prefixed with `iex>`) or a no-op line with documentation. Thus, multiline messages are not supported. ## When not to use doctest In general, doctests are not recommended when your code examples contain side effects. For example, if a doctest prints to standard output, doctest will not try to capture the output. Similarly, doctests do not run in any kind of sandbox. So any module defined in a code example is going to linger throughout the whole test suite run. """ defmodule Error do defexception [:message] end @doc """ This macro is used to generate ExUnit test cases for doctests. Calling `doctest(Module)` will generate tests for all doctests found in the module `Module` Options can also be supplied: * `:except` — generate tests for all functions except those listed (list of `{function, arity}` tuples, and/or `:moduledoc`). * `:only` — generate tests only for functions listed (list of `{function, arity}` tuples, and/or `:moduledoc`). * `:import` — when `true`, one can test a function defined in the module without referring to the module name. However, this is not feasible when there is a clash with a module like Kernel. In these cases, `import` should be set to `false` and a full `M.f` construct should be used. ## Examples doctest MyModule, except: [:moduledoc, trick_fun: 1] This macro is auto-imported with every `ExUnit.Case`. """ defmacro doctest(mod, opts \\ []) do require = if is_atom Macro.expand(mod, __CALLER__) do quote do require unquote(mod) end end tests = quote bind_quoted: binding do file = "(for doctest at) " <> Path.relative_to_cwd(mod.__info__(:compile)[:source]) for {name, test} <- ExUnit.DocTest.__doctests__(mod, opts) do @tag :doctest @file file test name, do: unquote(test) end end [require, tests] end @doc false def __doctests__(module, opts) do do_import = Keyword.get(opts, :import, false) extract(module) |> filter_by_opts(opts) |> Stream.with_index |> Enum.map(fn {test, acc} -> compile_test(test, module, do_import, acc + 1) end) end defp filter_by_opts(tests, opts) do only = opts[:only] || [] except = opts[:except] || [] tests |> Stream.reject(&(&1.fun_arity in except)) |> Stream.filter(&(Enum.empty?(only) or &1.fun_arity in only)) end ## Compilation of extracted tests defp compile_test(test, module, do_import, n) do {test_name(test, module, n), test_content(test, module, do_import)} end defp test_name(%{fun_arity: :moduledoc}, m, n) do "moduledoc at #{inspect m} (#{n})" end defp test_name(%{fun_arity: {f, a}}, m, n) do "doc at #{inspect m}.#{f}/#{a} (#{n})" end defp test_content(%{exprs: exprs, line: line, fun_arity: fun_arity}, module, do_import) do file = module.__info__(:compile)[:source] |> List.to_string location = [line: line, file: Path.relative_to_cwd(file)] stack = Macro.escape [{module, :__MODULE__, 0, location}] if multiple_exceptions?(exprs) do {fun, arity} = fun_arity raise Error, message: "multiple exceptions in one doctest case are not supported. " "Invalid doctest for #{inspect module}.#{fun}/#{arity}" end tests = Enum.map exprs, fn {expr, expected} -> test_case_content(expr, expected, module, line, file, stack) end quote do unquote_splicing(test_import(module, do_import)) unquote(gen_code_for_tests(tests, whole_expr(exprs), stack)) end end defp whole_expr(exprs) do Enum.map_join(exprs, "\n", &elem(&1, 0)) end defp multiple_exceptions?(exprs) do Enum.count(exprs, fn {_, {:error, _, _}} -> true _ -> false end) > 1 end defp gen_code_for_tests(tests, whole_expr, stack) do quote do stack = unquote(stack) try do # Put all tests into one context unquote_splicing(tests) rescue e in [ExUnit.AssertionError] -> reraise e, stack error -> reraise ExUnit.AssertionError, [message: "Doctest failed: got #{inspect(error.__struct__)} with message #{Exception.message(error)}", expr: unquote(whole_expr)], stack end end end defp test_case_content(expr, {:test, expected}, module, line, file, stack) do expr_ast = string_to_quoted(module, line, file, expr) expected_ast = string_to_quoted(module, line, file, expected) quote do expected = unquote(expected_ast) case unquote(expr_ast) do ^expected -> :ok actual -> reraise ExUnit.AssertionError, [message: "Doctest failed", expr: "#{unquote(String.strip(expr))} === #{unquote(String.strip(expected))}", left: actual], unquote(stack) end end end defp test_case_content(expr, {:inspect, expected}, module, line, file, stack) do expr_ast = quote do: inspect(unquote(string_to_quoted(module, line, file, expr))) expected_ast = string_to_quoted(module, line, file, expected) quote do expected = unquote(expected_ast) case unquote(expr_ast) do ^expected -> :ok actual -> reraise ExUnit.AssertionError, [message: "Doctest failed", expr: "inspect(#{unquote(String.strip(expr))}) === #{unquote(String.strip(expected))}", left: actual], unquote(stack) end end end defp test_case_content(expr, {:error, exception, message}, module, line, file, stack) do expr_ast = string_to_quoted(module, line, file, expr) quote do stack = unquote(stack) expr = unquote(String.strip(expr)) spec = inspect(unquote(exception)) <> " with message " <> inspect(unquote(message)) try do unquote(expr_ast) rescue error -> unless error.__struct__ == unquote(exception) and Exception.message(error) == unquote(message) do got = inspect(error.__struct__) <> " with message " <> inspect(Exception.message(error)) reraise ExUnit.AssertionError, [message: "Doctest failed: expected exception #{spec} but got #{got}", expr: expr], stack end else _ -> reraise ExUnit.AssertionError, [message: "Doctest failed: expected exception #{spec} but nothing was raised", expr: expr], stack end end end defp test_import(_mod, false), do: [] defp test_import(mod, _) do [quote do: import(unquote(mod))] end defp string_to_quoted(module, line, file, expr) do location = [line: line, file: Path.relative_to_cwd(file)] stack = Macro.escape [{module, :__MODULE__, 0, location}] try do Code.string_to_quoted!(expr, location) rescue e -> message = "(#{inspect e.__struct__}) #{Exception.message(e)}" quote do reraise ExUnit.AssertionError, [message: "Doctest did not compile, got: #{unquote(message)}", expr: unquote(String.strip(expr))], unquote(stack) end end end ## Extraction of the tests defp extract(module) do all_docs = Code.get_docs(module, :all) unless all_docs do raise Error, message: "could not retrieve the documentation for module #{inspect module}. " <> "The module was not compiled with documentation or its beam file cannot be accessed" end moduledocs = extract_from_moduledoc(all_docs[:moduledoc]) docs = for doc <- all_docs[:docs], doc <- extract_from_doc(doc), do: doc moduledocs ++ docs end defp extract_from_moduledoc({_, doc}) when doc in [false, nil], do: [] defp extract_from_moduledoc({line, doc}) do for test <- extract_tests(line, doc) do %{test | fun_arity: :moduledoc} end end defp extract_from_doc({_, _, _, _, doc}) when doc in [false, nil], do: [] defp extract_from_doc({fa, line, _, _, doc}) do for test <- extract_tests(line, doc) do %{test | fun_arity: fa} end end defp extract_tests(line, doc) do lines = String.split(doc, ~r/\n/, trim: false) |> adjust_indent extract_tests(lines, line, "", "", [], true) end defp adjust_indent(lines) do adjust_indent(lines, [], 0, :text) end defp adjust_indent([], adjusted_lines, _indent, _) do Enum.reverse adjusted_lines end @iex_prompt ["iex>", "iex("] @dot_prompt ["...>", "...("] defp adjust_indent([line|rest], adjusted_lines, indent, :text) do case String.starts_with?(String.lstrip(line), @iex_prompt) do true -> adjust_indent([line|rest], adjusted_lines, get_indent(line, indent), :prompt) false -> adjust_indent(rest, adjusted_lines, indent, :text) end end defp adjust_indent([line|rest], adjusted_lines, indent, check) when check in [:prompt, :after_prompt] do stripped_line = strip_indent(line, indent) case String.lstrip(line) do "" -> raise Error, message: "expected non-blank line to follow iex> prompt" ^stripped_line -> :ok _ -> raise Error, message: "indentation level mismatch: #{inspect line}, should have been #{indent} spaces" end if String.starts_with?(stripped_line, @iex_prompt ++ @dot_prompt) do adjust_indent(rest, [stripped_line|adjusted_lines], indent, :after_prompt) else next = if check == :prompt, do: :after_prompt, else: :code adjust_indent(rest, [stripped_line|adjusted_lines], indent, next) end end defp adjust_indent([line|rest], adjusted_lines, indent, :code) do stripped_line = strip_indent(line, indent) cond do stripped_line == "" -> adjust_indent(rest, [stripped_line|adjusted_lines], 0, :text) String.starts_with?(String.lstrip(line), @iex_prompt) -> adjust_indent([line|rest], adjusted_lines, indent, :prompt) true -> adjust_indent(rest, [stripped_line|adjusted_lines], indent, :code) end end defp get_indent(line, current_indent) do case Regex.run ~r/iex/, line, return: :index do [{pos, _len}] -> pos nil -> current_indent end end defp strip_indent(line, indent) do length = byte_size(line) - indent if length > 0 do :binary.part(line, indent, length) else "" end end defp extract_tests([], _line, "", "", [], _) do [] end defp extract_tests([], _line, "", "", acc, _) do Enum.reverse(reverse_last_test(acc)) end # End of input and we've still got a test pending. defp extract_tests([], _, expr_acc, expected_acc, [test=%{exprs: exprs}|t], _) do test = %{test | exprs: [{expr_acc, {:test, expected_acc}} | exprs]} Enum.reverse(reverse_last_test([test|t])) end # We've encountered the next test on an adjacent line. Put them into one group. defp extract_tests([<< "iex>", _ :: binary>>|_] = list, line, expr_acc, expected_acc, [test=%{exprs: exprs}|t], newtest) when expr_acc != "" and expected_acc != "" do test = %{test | exprs: [{expr_acc, {:test, expected_acc}} | exprs]} extract_tests(list, line, "", "", [test|t], newtest) end # Store expr_acc and start a new test case. defp extract_tests([<< "iex>", string :: binary>>|lines], line, "", expected_acc, acc, true) do acc = reverse_last_test(acc) test = %{line: line, fun_arity: nil, exprs: []} extract_tests(lines, line, string, expected_acc, [test|acc], false) end # Store expr_acc. defp extract_tests([<< "iex>", string :: binary>>|lines], line, "", expected_acc, acc, false) do extract_tests(lines, line, string, expected_acc, acc, false) end # Still gathering expr_acc. Synonym for the next clause. defp extract_tests([<< "iex>", string :: binary>>|lines], line, expr_acc, expected_acc, acc, newtest) do extract_tests(lines, line, expr_acc <> "\n" <> string, expected_acc, acc, newtest) end # Still gathering expr_acc. Synonym for the previous clause. defp extract_tests([<< "...>", string :: binary>>|lines], line, expr_acc, expected_acc, acc, newtest) when expr_acc != "" do extract_tests(lines, line, expr_acc <> "\n" <> string, expected_acc, acc, newtest) end # Expression numbers are simply skipped. defp extract_tests([<< "iex(", _ :: 8, string :: binary>>|lines], line, expr_acc, expected_acc, acc, newtest) do extract_tests(["iex" <> skip_iex_number(string)|lines], line, expr_acc, expected_acc, acc, newtest) end # Expression numbers are simply skipped redux. defp extract_tests([<< "...(", _ :: 8, string :: binary>>|lines], line, expr_acc, expected_acc, acc, newtest) do extract_tests(["..." <> skip_iex_number(string)|lines], line, expr_acc, expected_acc, acc, newtest) end # Skip empty or documentation line. defp extract_tests([_|lines], line, "", "", acc, _) do extract_tests(lines, line, "", "", acc, true) end # Encountered an empty line, store pending test defp extract_tests([""|lines], line, expr_acc, expected_acc, [test=%{exprs: exprs}|t], _) do test = %{test | exprs: [{expr_acc, {:test, expected_acc}} | exprs]} extract_tests(lines, line, "", "", [test|t], true) end # Exception test. defp extract_tests([<< "** (", string :: binary >>|lines], line, expr_acc, "", [test=%{exprs: exprs}|t], newtest) do test = %{test | exprs: [{expr_acc, extract_error(string, "")} | exprs]} extract_tests(lines, line, "", "", [test|t], newtest) end # Finally, parse expected_acc. defp extract_tests([expected|lines], line, expr_acc, expected_acc, [test=%{exprs: exprs}|t]=acc, newtest) do if expected =~ ~r/^#[A-Z][\w\.]*<.*>$/ do expected = expected_acc <> "\n" <> inspect(expected) test = %{test | exprs: [{expr_acc, {:inspect, expected}} | exprs]} extract_tests(lines, line, "", "", [test|t], newtest) else extract_tests(lines, line, expr_acc, expected_acc <> "\n" <> expected, acc, newtest) end end defp extract_error(<< ")", t :: binary >>, acc) do {:error, Module.concat([acc]), String.strip(t)} end defp extract_error(<< h, t :: binary >>, acc) do extract_error(t, << acc :: binary, h >>) end defp skip_iex_number(<< ")", ">", string :: binary >>) do ">" <> string end defp skip_iex_number(<< _ :: 8, string :: binary >>) do skip_iex_number(string) end defp reverse_last_test([]), do: [] defp reverse_last_test([test=%{exprs: exprs} | t]) do test = %{test | exprs: Enum.reverse(exprs)} [test | t] end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/event_manager.ex000066400000000000000000000024701254730255300247330ustar00rootroot00000000000000# This module publishes events during the test suite run. # This is used, for example, by formatters to print user # information as well as internal statistics for ExUnit. defmodule ExUnit.EventManager do @moduledoc false def start_link() do :gen_event.start_link() end def add_handler(ref, handler, args) do :gen_event.add_handler(ref, handler, args) end def delete_handler(ref, handler, args) do :gen_event.delete_handler(ref, handler, args) end def which_handlers(ref) do :gen_event.which_handlers(ref) end def call(ref, handler, request) do :gen_event.call(ref, handler, request) end def call(ref, handler, request, timeout) do :gen_event.call(ref, handler, request, timeout) end def suite_started(ref, opts) do :gen_event.notify(ref, {:suite_started, opts}) end def suite_finished(ref, load_us, run_us) do :gen_event.notify(ref, {:suite_finished, load_us, run_us}) end def case_started(ref, test_case) do :gen_event.notify(ref, {:case_started, test_case}) end def case_finished(ref, test_case) do :gen_event.notify(ref, {:case_finished, test_case}) end def test_started(ref, test) do :gen_event.notify(ref, {:test_started, test}) end def test_finished(ref, test) do :gen_event.notify(ref, {:test_finished, test}) end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/filters.ex000066400000000000000000000075331254730255300235750ustar00rootroot00000000000000defmodule ExUnit.Filters do @moduledoc """ Conveniences for parsing and evaluating filters. """ @type t :: list({atom, Regex.t | String.Chars.t} | atom) @doc """ Parses filters out of a path. Determines whether a given file path (supplied to ExUnit/Mix as arguments on the command line) includes a line number filter, and if so returns the appropriate ExUnit configuration options. """ @spec parse_path(String.t) :: {String.t, any} def parse_path(file) do case Regex.run(~r/^(.+):(\d+)$/, file, capture: :all_but_first) do [file, line_number] -> {file, exclude: [:test], include: [line: line_number]} nil -> {file, []} end end @doc """ Normalizes include and excludes to remove duplicates and keep precedence. ## Examples iex> ExUnit.Filters.normalize(nil, nil) {[], []} iex> ExUnit.Filters.normalize([:foo, :bar, :bar], [:foo, :baz]) {[:foo, :bar], [:baz]} """ @spec normalize(t | nil, t | nil) :: {t, t} def normalize(include, exclude) do include = include |> List.wrap |> Enum.uniq exclude = exclude |> List.wrap |> Enum.uniq |> Kernel.--(include) {include, exclude} end @doc """ Parses the given filters, as one would receive from the command line. ## Examples iex> ExUnit.Filters.parse(["foo:bar", "baz", "line:9", "bool:true"]) [{:foo, "bar"}, :baz, {:line, "9"}, {:bool, "true"}] """ @spec parse([String.t]) :: t def parse(filters) do Enum.map filters, fn filter -> case String.split(filter, ":", parts: 2) do [key, value] -> {String.to_atom(key), value} [key] -> String.to_atom(key) end end end @doc """ Evaluates the `include` and `exclude` filters against the given `tags`. Some filters, like `:line`, may require the whole test collection to find the closest line, that's why it must also be passed as argument. Filters can either be a regular expression or any data structure that implements to `String.Chars`, which is invoked before comparing the filter with the tag value. ## Examples iex> ExUnit.Filters.eval([foo: "bar"], [:foo], %{foo: "bar"}, []) :ok iex> ExUnit.Filters.eval([foo: "bar"], [:foo], %{foo: "baz"}, []) {:error, :foo} """ @spec eval(t, t, map, [ExUnit.Test.t]) :: :ok | {:error, atom} def eval(include, exclude, tags, collection) when is_map(tags) do excluded = Enum.find_value exclude, &has_tag(&1, tags, collection) if !excluded or Enum.any?(include, &has_tag(&1, tags, collection)) do :ok else {:error, excluded} end end defp has_tag({:line, line}, tags, collection) do line = to_integer(line) tags.line <= line and closest_test_before_line(line, collection).tags.line == tags.line end defp has_tag({key, %Regex{} = value}, tags, _collection) when is_atom(key) do case Map.fetch(tags, key) do {:ok, tag} -> to_string(tag) =~ value and key _ -> false end end defp has_tag({key, value}, tags, _collection) when is_atom(key) do case Map.fetch(tags, key) do {:ok, ^value} -> key {:ok, tag} -> compare(to_string(tag), to_string(value)) and key _ -> false end end defp has_tag(key, tags, _collection) when is_atom(key), do: Map.has_key?(tags, key) and key defp to_integer(integer) when is_integer(integer), do: integer defp to_integer(integer) when is_binary(integer), do: String.to_integer(integer) defp compare("Elixir." <> tag1, tag2), do: compare(tag1, tag2) defp compare(tag1, "Elixir." <> tag2), do: compare(tag1, tag2) defp compare(tag, tag), do: true defp compare(_, _), do: false defp closest_test_before_line(line, collection) do Enum.min_by(collection, fn %ExUnit.Test{tags: %{line: test_line}} -> if line - test_line >= 0 do line - test_line else :infinity end end) end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/formatter.ex000066400000000000000000000170151254730255300241240ustar00rootroot00000000000000defmodule ExUnit.Formatter do @moduledoc """ This module holds helper functions related to formatting and contains documentation about the formatting protocol. Formatters are registered at the `ExUnit.EventManager` event manager and will be send events by the runner. The following events are possible: * `{:suite_started, opts}` - the suite has started with the specified options to the runner. * `{:suite_finished, run_us, load_us}` - the suite has finished. `run_us` and `load_us` are the run and load times in microseconds respectively. * `{:case_started, test_case}` - a test case has started. See `ExUnit.TestCase` for details. * `{:case_finished, test_case}` - a test case has finished. See `ExUnit.TestCase` for details. * `{:test_started, test_case}` - a test case has started. See `ExUnit.Test` for details. * `{:test_finished, test_case}` - a test case has finished. See `ExUnit.Test` for details. """ @type id :: term @type test_case :: ExUnit.TestCase.t @type test :: ExUnit.Test.t @type run_us :: pos_integer @type load_us :: pos_integer | nil import Exception, only: [format_stacktrace_entry: 1] @label_padding " " @counter_padding " " @inspect_padding @counter_padding <> @label_padding @doc """ Formats time taken running the test suite. It receives the time spent running the tests and optionally the time spent loading the test suite. ## Examples iex> format_time(10000, nil) "Finished in 0.01 seconds" iex> format_time(10000, 20000) "Finished in 0.03 seconds (0.02s on load, 0.01s on tests)" iex> format_time(10000, 200000) "Finished in 0.2 seconds (0.2s on load, 0.01s on tests)" """ @spec format_time(run_us, load_us) :: String.t def format_time(run_us, nil) do "Finished in #{run_us |> normalize_us |> format_us} seconds" end def format_time(run_us, load_us) do run_us = run_us |> normalize_us load_us = load_us |> normalize_us ms = run_us + load_us "Finished in #{format_us ms} seconds (#{format_us load_us}s on load, #{format_us run_us}s on tests)" end defp normalize_us(us) do div(us, 10000) end defp format_us(us) do if us < 10 do "0.0#{us}" else us = div us, 10 "#{div(us, 10)}.#{rem(us, 10)}" end end @doc """ Formats filters used to constrain cases to be run. ## Examples iex> format_filters([run: true, slow: false], :include) "Including tags: [run: true, slow: false]" """ @spec format_filters(Keyword.t, atom) :: String.t def format_filters(filters, type) do case type do :include -> "Including tags: #{inspect filters}" :exclude -> "Excluding tags: #{inspect filters}" end end @doc """ Receives a test and formats its failure. """ def format_test_failure(test, failure, counter, width, formatter) def format_test_failure(test, {kind, reason, stack}, counter, width, formatter) do %ExUnit.Test{name: name, case: case, tags: tags} = test test_info(with_counter(counter, "#{name} (#{inspect case})"), formatter) <> test_location(with_location(tags), formatter) <> format_kind_reason(kind, reason, width, formatter) <> format_stacktrace(stack, case, name, formatter) end @doc """ Receives a test case and formats its failure. """ def format_test_case_failure(test_case, failure, counter, width, formatter) def format_test_case_failure(test_case, {kind, reason, stacktrace}, counter, width, formatter) do %ExUnit.TestCase{name: name} = test_case test_case_info(with_counter(counter, "#{inspect name}: "), formatter) <> format_kind_reason(kind, reason, width, formatter) <> format_stacktrace(stacktrace, name, nil, formatter) end defp format_kind_reason(:error, %ExUnit.AssertionError{} = struct, width, formatter) do width = if width == :infinity, do: width, else: width - byte_size(@inspect_padding) fields = [note: if_value(struct.message, &format_banner(&1, formatter)), code: if_value(struct.expr, &code_multiline(&1, width)), lhs: if_value(struct.left, &inspect_multiline(&1, width)), rhs: if_value(struct.right, &inspect_multiline(&1, width))] fields |> filter_interesting_fields |> format_each_reason(formatter) |> make_into_lines(@counter_padding) end defp format_kind_reason(kind, reason, _width, formatter) do error_info Exception.format_banner(kind, reason), formatter end defp filter_interesting_fields(fields) do Enum.filter(fields, fn {_, value} -> value != ExUnit.AssertionError.no_value end) end defp format_each_reason(reasons, formatter) do Enum.map(reasons, fn {label, value} -> format_label(label, formatter) <> value end) end defp if_value(value, fun) do if value == ExUnit.AssertionError.no_value do value else fun.(value) end end defp format_label(:note, _formatter) do "" end defp format_label(label, formatter) do formatter.(:error_info, String.ljust("#{label}:", byte_size(@label_padding))) end defp format_banner(value, formatter) do value = String.replace(value, "\n", "\n" <> @counter_padding) formatter.(:error_info, value) end defp code_multiline(expr, _width) when is_binary(expr) do expr |> String.replace("\n", "\n" <> @inspect_padding) end defp code_multiline(expr, width) do code_multiline(expr |> Macro.to_string, width) end defp inspect_multiline(expr, width) do expr |> inspect(pretty: true, width: width) |> String.replace("\n", "\n" <> @inspect_padding) end defp make_into_lines(reasons, padding) do padding <> Enum.join(reasons, "\n" <> padding) <> "\n" end defp format_stacktrace([], _case, _test, _color) do "" end defp format_stacktrace(stacktrace, test_case, test, color) do extra_info("stacktrace:", color) <> Enum.map_join(stacktrace, fn(s) -> stacktrace_info format_stacktrace_entry(s, test_case, test), color end) end defp format_stacktrace_entry({test_case, test, _, location}, test_case, test) do "#{location[:file]}:#{location[:line]}" end defp format_stacktrace_entry(s, _test_case, _test) do format_stacktrace_entry(s) end defp with_location(tags) do "#{Path.relative_to_cwd(tags[:file])}:#{tags[:line]}" end defp with_counter(counter, msg) when counter < 10 do " #{counter}) #{msg}" end defp with_counter(counter, msg) when counter < 100 do " #{counter}) #{msg}" end defp with_counter(counter, msg) do "#{counter}) #{msg}" end defp test_case_info(msg, nil), do: msg <> "failure on setup_all callback, tests invalidated\n" defp test_case_info(msg, formatter), do: test_case_info(formatter.(:test_case_info, msg), nil) defp test_info(msg, nil), do: msg <> "\n" defp test_info(msg, formatter), do: test_info(formatter.(:test_info, msg), nil) defp test_location(msg, nil), do: " " <> msg <> "\n" defp test_location(msg, formatter), do: test_location(formatter.(:location_info, msg), nil) defp error_info(msg, nil) do " " <> String.replace(msg, "\n", "\n ") <> <<"\n">> end defp error_info(msg, formatter), do: error_info(formatter.(:error_info, msg), nil) defp extra_info(msg, nil), do: " " <> msg <> "\n" defp extra_info(msg, formatter), do: extra_info(formatter.(:extra_info, msg), nil) defp stacktrace_info(msg, nil), do: " " <> msg <> "\n" defp stacktrace_info(msg, formatter), do: stacktrace_info(formatter.(:stacktrace_info, msg), nil) end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/on_exit_handler.ex000066400000000000000000000044131254730255300252610ustar00rootroot00000000000000defmodule ExUnit.OnExitHandler do @moduledoc false @name __MODULE__ def start_link do Agent.start_link(fn -> %{} end, name: @name) end @spec register(pid) :: :ok def register(pid) do Agent.update(@name, &Map.put(&1, pid, [])) end @spec add(pid, term, fun) :: :ok | :error def add(pid, ref, callback) do Agent.get_and_update(@name, fn map -> if entries = Map.get(map, pid) do entries = List.keystore(entries, ref, 0, {ref, callback}) {:ok, Map.put(map, pid, entries)} else {:error, map} end end) end @spec run(pid) :: :ok | {Exception.kind, term, Exception.stacktrace} def run(pid) do callbacks = Agent.get_and_update(@name, &Map.pop(&1, pid)) exec_on_exit_callbacks(Enum.reverse(callbacks)) end defp exec_on_exit_callbacks(callbacks) do {runner_pid, runner_monitor, state} = Enum.reduce callbacks, {nil, nil, nil}, &exec_on_exit_callback/2 if is_pid(runner_pid) and Process.alive?(runner_pid) do send(runner_pid, :shutdown) receive do {:DOWN, ^runner_monitor, :process, ^runner_pid, _error} -> :ok end end state || :ok end defp exec_on_exit_callback({_ref, callback}, {runner_pid, runner_monitor, state}) do {runner_pid, runner_monitor} = ensure_alive_callback_runner(runner_pid, runner_monitor) send(runner_pid, {:run, self(), callback}) receive do {^runner_pid, nil} -> {runner_pid, runner_monitor, state} {^runner_pid, error} -> {runner_pid, runner_monitor, state || error} {:DOWN, ^runner_monitor, :process, ^runner_pid, error} -> {nil, nil, state || {{:EXIT, runner_pid}, error, []}} end end ## Runner @doc false def on_exit_runner_loop do receive do {:run, from, fun} -> send(from, {self(), exec_callback(fun)}) on_exit_runner_loop() :shutdown -> :ok end end defp ensure_alive_callback_runner(nil, nil) do spawn_monitor(__MODULE__, :on_exit_runner_loop, []) end defp ensure_alive_callback_runner(runner_pid, runner_monitor) do {runner_pid, runner_monitor} end defp exec_callback(callback) do callback.() nil catch kind, error -> {kind, Exception.normalize(kind, error), System.stacktrace} end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/runner.ex000066400000000000000000000232641254730255300234350ustar00rootroot00000000000000defmodule ExUnit.Runner do @moduledoc false alias ExUnit.EventManager, as: EM def run(async, sync, opts, load_us) do {opts, config} = configure(opts) {run_us, _} = :timer.tc fn -> EM.suite_started(config.manager, opts) loop %{config | sync_cases: shuffle(config, sync), async_cases: shuffle(config, async)} end EM.suite_finished(config.manager, run_us, load_us) EM.call(config.manager, ExUnit.RunnerStats, :stop, :infinity) end def configure(opts) do opts = normalize_opts(opts) {:ok, pid} = EM.start_link formatters = [ExUnit.RunnerStats|opts[:formatters]] Enum.each formatters, &(:ok = EM.add_handler(pid, &1, opts)) config = %{ async_cases: [], exclude: opts[:exclude], include: opts[:include], manager: pid, max_cases: opts[:max_cases], seed: opts[:seed], sync_cases: [], taken_cases: 0, timeout: opts[:timeout], trace: opts[:trace] } {opts, config} end defp normalize_opts(opts) do {include, exclude} = ExUnit.Filters.normalize(opts[:include], opts[:exclude]) opts |> Keyword.put(:exclude, exclude) |> Keyword.put(:include, include) |> Keyword.put(:max_cases, max_cases(opts)) |> Keyword.put_new(:seed, :os.timestamp |> elem(2)) end defp max_cases(opts) do cond do opts[:trace] -> 1 max = opts[:max_cases] -> max true -> :erlang.system_info(:schedulers_online) end end defp loop(config) do available = config.max_cases - config.taken_cases cond do # No cases available, wait for one available <= 0 -> wait_until_available config # Slots are available, start with async cases tuple = take_async_cases(config, available) -> {config, cases} = tuple spawn_cases(config, cases) # No more async cases, wait for them to finish config.taken_cases > 0 -> wait_until_available config # So we can start all sync cases tuple = take_sync_cases(config) -> {config, cases} = tuple spawn_cases(config, cases) # No more cases, we are done! true -> config end end # Loop expecting messages from the spawned cases. Whenever # a test case has finished executing, decrease the taken # cases counter and attempt to spawn new ones. defp wait_until_available(config) do receive do {_pid, :case_finished, _test_case} -> loop %{config | taken_cases: config.taken_cases - 1} end end defp spawn_cases(config, cases) do pid = self() Enum.each cases, fn case_name -> spawn_link fn -> run_case(config, pid, case_name) end end loop %{config | taken_cases: config.taken_cases + length(cases)} end defp run_case(config, pid, case_name) do test_case = case_name.__ex_unit__(:case) EM.case_started(config.manager, test_case) # Prepare tests, selecting which ones should # run and which ones were skipped. tests = prepare_tests(config, test_case.tests) {test_case, pending} = if Enum.all?(tests, &(&1.state)) do {test_case, tests} else spawn_case(config, test_case, tests) end # Run the pending tests. We don't actually spawn those # tests but we do send the notifications to formatter. Enum.each pending, &run_test(config, &1, []) EM.case_finished(config.manager, test_case) send pid, {self, :case_finished, test_case} end defp prepare_tests(config, tests) do tests = shuffle(config, tests) include = config.include exclude = config.exclude for test <- tests do tags = Map.put(test.tags, :test, test.name) case ExUnit.Filters.eval(include, exclude, tags, tests) do :ok -> %{test | tags: tags} {:error, tag} -> %{test | state: {:skip, "due to #{tag} filter"}} end end end defp spawn_case(config, test_case, tests) do parent = self {case_pid, case_ref} = spawn_monitor(fn -> ExUnit.OnExitHandler.register(self) case exec_case_setup(test_case) do {:ok, test_case, context} -> Enum.each(tests, &run_test(config, &1, context)) send parent, {self, :case_finished, test_case, []} {:error, test_case} -> failed_tests = Enum.map(tests, & %{&1 | state: {:invalid, test_case}}) send parent, {self, :case_finished, test_case, failed_tests} end exit(:shutdown) end) {test_case, pending} = receive do {^case_pid, :case_finished, test_case, tests} -> receive do {:DOWN, ^case_ref, :process, ^case_pid, _} -> :ok end {test_case, tests} {:DOWN, ^case_ref, :process, ^case_pid, error} -> test_case = %{test_case | state: {:failed, {{:EXIT, case_pid}, error, []}}} {test_case, []} end {exec_on_exit(test_case, case_pid), pending} end defp exec_case_setup(%ExUnit.TestCase{name: case_name} = test_case) do {:ok, context} = case_name.__ex_unit__(:setup_all, %{case: case_name}) {:ok, test_case, context} catch kind, error -> failed = {:failed, {kind, Exception.normalize(kind, error), pruned_stacktrace}} {:error, %{test_case | state: failed}} end defp run_test(true, config, test, context) do run_test([], config, test, context) end defp run_test(false, config, test, context) do spawn_test(config, test, context) end defp run_test(opts, config, test, context) do ref = make_ref() try do ExUnit.CaptureLog.capture_log(opts, fn -> send self(), {ref, spawn_test(config, test, context)} end) catch :exit, :noproc -> message = "could not run test, it uses @tag :capture_log" <> " but the :logger application is not running" %{test | state: {:failed, {:error, RuntimeError.exception(message), []}}} else logged -> receive do {^ref, test} -> %{test | logs: logged} end end end defp run_test(config, %{tags: tags} = test, context) do EM.test_started(config.manager, test) if is_nil(test.state) do capture_log? = Map.get(tags, :capture_log, false) test = run_test(capture_log?, config, test, Map.merge(tags, context)) end EM.test_finished(config.manager, test) end defp spawn_test(config, test, context) do parent = self() {test_pid, test_ref} = spawn_monitor(fn -> ExUnit.OnExitHandler.register(self) {us, test} = :timer.tc(fn -> case exec_test_setup(test, context) do {:ok, test, context} -> exec_test(test, context) {:error, test} -> test end end) send parent, {self, :test_finished, %{test | time: us}} exit(:shutdown) end) timeout = get_timeout(test.tags, config) test = receive do {^test_pid, :test_finished, test} -> receive do {:DOWN, ^test_ref, :process, ^test_pid, _} -> :ok end test {:DOWN, ^test_ref, :process, ^test_pid, error} -> %{test | state: {:failed, {{:EXIT, test_pid}, error, []}}} after timeout -> stacktrace = try do Process.info(test_pid, :current_stacktrace) catch _, _ -> [] else {:current_stacktrace, stacktrace} -> stacktrace end Process.exit(test_pid, :kill) Process.demonitor(test_ref, [:flush]) %{test | state: {:failed, {:error, %ExUnit.TimeoutError{timeout: timeout}, stacktrace}}} end exec_on_exit(test, test_pid) end defp exec_test_setup(%ExUnit.Test{case: case} = test, context) do {:ok, context} = case.__ex_unit__(:setup, context) {:ok, test, context} catch kind2, error2 -> failed = {:failed, {kind2, Exception.normalize(kind2, error2), pruned_stacktrace()}} {:error, %{test | state: failed}} end defp exec_test(%ExUnit.Test{case: case, name: name} = test, context) do apply(case, name, [context]) test catch kind, error -> failed = {:failed, {kind, Exception.normalize(kind, error), pruned_stacktrace()}} %{test | state: failed} end defp exec_on_exit(test_or_case, pid) do case ExUnit.OnExitHandler.run(pid) do :ok -> test_or_case {kind, reason, stack} -> state = test_or_case.state || {:failed, {kind, reason, prune_stacktrace(stack)}} %{test_or_case | state: state} end end ## Helpers defp get_timeout(tags, config) do if config.trace do :infinity else Map.get(tags, :timeout, config.timeout) end end defp shuffle(%{seed: 0}, list) do Enum.reverse(list) end defp shuffle(%{seed: seed}, list) do _ = :random.seed(3172, 9814, seed) Enum.shuffle(list) end defp take_async_cases(config, count) do case config.async_cases do [] -> nil cases -> {response, remaining} = Enum.split(cases, count) {%{config | async_cases: remaining}, response} end end defp take_sync_cases(config) do case config.sync_cases do [h|t] -> {%{config | sync_cases: t}, [h]} [] -> nil end end defp pruned_stacktrace, do: prune_stacktrace(System.stacktrace) # Assertions can pop-up in the middle of the stack defp prune_stacktrace([{ExUnit.Assertions, _, _, _}|t]), do: prune_stacktrace(t) # As soon as we see a Runner, it is time to ignore the stacktrace defp prune_stacktrace([{ExUnit.Runner, _, _, _}|_]), do: [] # All other cases defp prune_stacktrace([h|t]), do: [h|prune_stacktrace(t)] defp prune_stacktrace([]), do: [] end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/runner_stats.ex000066400000000000000000000015341254730255300246470ustar00rootroot00000000000000# Small event consumer to handle runner statistics. defmodule ExUnit.RunnerStats do @moduledoc false use GenEvent def init(_opts) do {:ok, %{total: 0, failures: 0, skipped: 0}} end def handle_call(:stop, map) do {:remove_handler, map} end def handle_event({:test_finished, %ExUnit.Test{state: {tag, _}}}, %{total: total, failures: failures} = map) when tag in [:failed, :invalid] do {:ok, %{map | total: total + 1, failures: failures + 1}} end def handle_event({:test_finished, %ExUnit.Test{state: {:skip, _}}}, %{total: total, skipped: skipped} = map) do {:ok, %{map | total: total + 1, skipped: skipped + 1}} end def handle_event({:test_finished, _}, %{total: total} = map) do {:ok, %{map | total: total + 1}} end def handle_event(_, map) do {:ok, map} end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/lib/ex_unit/server.ex000066400000000000000000000065641254730255300234360ustar00rootroot00000000000000defmodule ExUnit.Server do @moduledoc false @timeout 30_000 use GenServer def start_link() do GenServer.start_link(__MODULE__, :ok, name: __MODULE__) end ## Before run API def start_load() do GenServer.cast(__MODULE__, :start_load) end def add_async_case(name) do GenServer.cast(__MODULE__, {:add_async_case, name}) end def add_sync_case(name) do GenServer.cast(__MODULE__, {:add_sync_case, name}) end ## After run API def start_run() do GenServer.call(__MODULE__, :start_run, @timeout) end ## Capture Device API def add_device(device) do GenServer.call(__MODULE__, {:add_device, device}) end def remove_device(device) do GenServer.call(__MODULE__, {:remove_device, device}) end def log_capture_on(pid) do GenServer.call(__MODULE__, {:log_capture_on, pid}) end def log_capture_off(ref) do GenServer.call(__MODULE__, {:log_capture_off, ref}) end ## Callbacks def init(:ok) do {:ok, %{ async_cases: HashSet.new, sync_cases: HashSet.new, start_load: :os.timestamp, captured_devices: HashSet.new, log_captures: HashSet.new, log_status: nil }} end def handle_call(:start_run, _from, config) do load_us = if start_load = config.start_load do :timer.now_diff(:os.timestamp, start_load) end {:reply, {config.async_cases, config.sync_cases, load_us}, %{config | async_cases: HashSet.new, sync_cases: HashSet.new, start_load: nil}} end def handle_call({:add_device, device}, _from, config) do {:reply, not(device in config.captured_devices), %{config | captured_devices: Set.put(config.captured_devices, device)}} end def handle_call({:remove_device, device}, _from, config) do {:reply, :ok, %{config | captured_devices: Set.delete(config.captured_devices, device)}} end def handle_call({:log_capture_on, pid}, _from, config) do ref = Process.monitor(pid) refs = HashSet.put(config.log_captures, ref) if HashSet.size(refs) == 1 do status = Logger.remove_backend(:console) {:reply, {:ok, ref}, %{config | log_captures: refs, log_status: status}} else {:reply, {:ok, ref}, %{config | log_captures: refs}} end end def handle_call({:log_capture_off, ref}, _from, config) do Process.demonitor(ref, [:flush]) config = remove_log_capture(ref, config) {:reply, :ok, config} end def handle_cast(:start_load, config) do {:noreply, %{config | start_load: :os.timestamp}} end def handle_cast({:add_async_case, name}, config) do {:noreply, %{config | async_cases: Set.put(config.async_cases, name)}} end def handle_cast({:add_sync_case, name}, config) do {:noreply, %{config | sync_cases: Set.put(config.sync_cases, name)}} end def handle_info({:DOWN, ref, _, _, _}, config) do config = remove_log_capture(ref, config) {:noreply, config} end def handle_info(_msg, state) do {:noreply, state} end defp remove_log_capture(ref, %{log_captures: refs} = config) do if ref in refs do refs = HashSet.delete(refs, ref) maybe_add_console(refs, config.log_status) %{config | log_captures: refs} else config end end defp maybe_add_console(refs, status) do if status == :ok and HashSet.size(refs) == 0 do Logger.add_backend(:console, flush: true) end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/mix.exs000066400000000000000000000011451254730255300206550ustar00rootroot00000000000000defmodule ExUnit.Mixfile do use Mix.Project def project do [app: :ex_unit, version: System.version, build_per_environment: false] end def application do [registered: [ExUnit.Server], mod: {ExUnit, []}, env: [ # Calculated on demand # max_cases: :erlang.system_info(:schedulers_online), # seed: rand(), assert_receive_timeout: 100, autorun: true, colors: [], exclude: [], include: [], formatters: [ExUnit.CLIFormatter], refute_receive_timeout: 100, timeout: 60_000, trace: false]] end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/000077500000000000000000000000001254730255300203155ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/000077500000000000000000000000001254730255300217705ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/assertions_test.exs000066400000000000000000000246571254730255300257600ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.AssertionsTest.Value do def tuple, do: {2, 1} def falsy, do: false def truthy, do: true end alias ExUnit.AssertionsTest.Value defmodule ExUnit.AssertionsTest do use ExUnit.Case, async: true test "assert with true value" do true = assert Value.truthy end test "assert with message when value is false" do try do "This should never be tested" = assert false, "This should be true" rescue error in [ExUnit.AssertionError] -> "This should be true" = error.message end end test "assert when value evaluates to false" do try do "This should never be tested" = assert Value.falsy rescue error in [ExUnit.AssertionError] -> "Value.falsy()" = error.expr |> Macro.to_string "Expected truthy, got false" = error.message end end test "assert with equality" do try do "This should never be tested" = assert 1 + 1 == 1 rescue error in [ExUnit.AssertionError] -> 1 = error.right 2 = error.left "1 + 1 == 1" = error.expr |> Macro.to_string end end test "assert with equality in reverse" do try do "This should never be tested" = assert 1 == 1 + 1 rescue error in [ExUnit.AssertionError] -> 1 = error.left 2 = error.right "1 == 1 + 1" = error.expr |> Macro.to_string end end test "refute when value is false" do false = refute false end test "refute when value evaluates to true" do try do refute Value.truthy raise "refute was supposed to fail" rescue error in [ExUnit.AssertionError] -> "Value.truthy()" = error.expr |> Macro.to_string "Expected false or nil, got true" = error.message end end test "assert match when equal" do {2, 1} = (assert {2, 1} = Value.tuple) end test "assert receive waits" do parent = self spawn fn -> send parent, :hello end :hello = assert_receive :hello end test "assert received does not wait" do send self, :hello :hello = assert_received :hello end test "assert received when empty mailbox" do try do "This should never be tested" = assert_received :hello rescue error in [ExUnit.AssertionError] -> "No message matching :hello after 0ms. The process mailbox is empty." = error.message end end test "assert received when different message" do send self, {:message, :not_expected, :at_all} try do "This should never be tested" = assert_received :hello rescue error in [ExUnit.AssertionError] -> "No message matching :hello after 0ms. Process mailbox:\n{:message, :not_expected, :at_all}" = error.message end end test "assert received when different message having more than 10 on mailbox" do for i <- 1..11, do: send(self, {:message, i}) try do "This should never be tested" = assert_received x when x == :hello rescue error in [ExUnit.AssertionError] -> "No message matching x when x == :hello after 0ms. Process mailbox:\n" <> "{:message, 1}\n{:message, 2}\n{:message, 3}\n{:message, 4}\n" <> "{:message, 5}\n{:message, 6}\n{:message, 7}\n{:message, 8}\n" <> "{:message, 9}\n{:message, 10}\nShowing only 10 of 11 messages." = error.message end end test "assert received leaks" do send self, {:hello, :world} assert_received {:hello, world} :world = world end test "refute received does not wait" do false = refute_received :hello end test "refute receive waits" do false = refute_receive :hello end test "refute received when equal" do send self, :hello try do "This should never be tested" = refute_received :hello rescue error in [ExUnit.AssertionError] -> "Unexpectedly received message :hello (which matched :hello)" = error.message end end test "assert in when member" do true = assert 'foo' in ['foo', 'bar'] end test "assert in when is not member" do try do "This should never be tested" = assert 'foo' in 'bar' rescue error in [ExUnit.AssertionError] -> 'foo' = error.left 'bar' = error.right "'foo' in 'bar'" = error.expr |> Macro.to_string end end test "refute in when is not member" do false = refute 'baz' in ['foo', 'bar'] end test "refute in when is member" do try do "This should never be tested" = refute 'foo' in ['foo', 'bar'] rescue error in [ExUnit.AssertionError] -> 'foo' = error.left ['foo', 'bar'] = error.right "'foo' in ['foo', 'bar']" = error.expr |> Macro.to_string end end test "assert match" do {:ok, true} = assert {:ok, _} = {:ok, true} end test "assert match when no match" do try do "This should never be tested" = assert {:ok, _} = "bar" rescue error in [ExUnit.AssertionError] -> "match (=) failed" = error.message "{:ok, _} = \"bar\"" = error.expr |> Macro.to_string "bar" = error.right end end test "refute match when no match" do try do "This should never be tested" = refute _ = "bar" rescue error in [ExUnit.AssertionError] -> "bar" = error.right "_ = \"bar\"" = error.expr |> Macro.to_string "match (=) succeeded, but should have failed" = error.message end end test "assert regex match" do true = assert "foo" =~ ~r(o) end test "assert regex match when no match" do try do "This should never be tested" = assert "foo" =~ ~r(a) rescue error in [ExUnit.AssertionError] -> "foo" = error.left ~r{a} = error.right end end test "refute regex match" do false = refute "foo" =~ ~r(a) end test "refute regex match when match" do try do "This should never be tested" = refute "foo" =~ ~r(o) rescue error in [ExUnit.AssertionError] -> "foo" = error.left ~r"o" = error.right end end test "assert raise with no error" do "This should never be tested" = assert_raise ArgumentError, fn -> # nothing end rescue error in [ExUnit.AssertionError] -> "Expected exception ArgumentError but nothing was raised" = error.message end test "assert raise with error" do error = assert_raise ArgumentError, fn -> raise ArgumentError, "test error" end "test error" = error.message end test "assert raise with some other error" do "This should never be tested" = assert_raise ArgumentError, fn -> Not.Defined.function(1, 2, 3) end rescue error in [ExUnit.AssertionError] -> "Expected exception ArgumentError but got UndefinedFunctionError " <> "(undefined function: Not.Defined.function/3 (module Not.Defined is not available))" = error.message end test "assert raise with erlang error" do assert_raise SyntaxError, fn -> List.flatten(1) end rescue error in [ExUnit.AssertionError] -> "Expected exception SyntaxError but got FunctionClauseError (no function clause matching in :lists.flatten/1)" = error.message end test "assert greater than operator" do true = assert 2 > 1 end test "assert greater than operator error" do "This should never be tested" = assert 1 > 2 rescue error in [ExUnit.AssertionError] -> 1 = error.left 2 = error.right "1 > 2" = error.expr |> Macro.to_string end test "assert less or equal than operator" do true = assert 1 <= 2 end test "assert less or equal than operator error" do "This should never be tested" = assert 2 <= 1 rescue error in [ExUnit.AssertionError] -> "2 <= 1" = error.expr |> Macro.to_string 2 = error.left 1 = error.right end test "assert operator with expressions" do greater = 5 true = assert 1 + 2 < greater end test "assert operator with custom message" do "This should never be tested" = assert 1 > 2, "assertion" rescue error in [ExUnit.AssertionError] -> "assertion" = error.message end test "assert in delta" do true = assert_in_delta(1.1, 1.2, 0.2) end test "assert in delta error" do "This should never be tested" = assert_in_delta(10, 12, 1) rescue error in [ExUnit.AssertionError] -> "Expected the difference between 10 and 12 (2) to be less than 1" = error.message end test "assert in delta with message" do "This should never be tested" = assert_in_delta(10, 12, 1, "test message") rescue error in [ExUnit.AssertionError] -> "test message" = error.message end test "refute in delta" do false = refute_in_delta(1.1, 1.5, 0.2) end test "refute in delta error" do "This should never be tested" = refute_in_delta(10, 11, 2) rescue error in [ExUnit.AssertionError] -> "Expected the difference between 10 and 11 (1) to be more than 2" = error.message end test "refute in delta with message" do "This should never be tested" = refute_in_delta(10, 11, 2, "test message") rescue error in [ExUnit.AssertionError] -> "test message (difference between 10 and 11 is less than 2)" = error.message end test "catch_throw with no throw" do catch_throw(1) rescue error in [ExUnit.AssertionError] -> "Expected to catch throw, got nothing" = error.message end test "catch_error with no error" do catch_error(1) rescue error in [ExUnit.AssertionError] -> "Expected to catch error, got nothing" = error.message end test "catch_exit with no exit" do catch_exit(1) rescue error in [ExUnit.AssertionError] -> "Expected to catch exit, got nothing" = error.message end test "catch_throw with throw" do 1 = catch_throw(throw 1) end test "catch_exit with exit" do 1 = catch_exit(exit 1) end test "catch_error with error" do :function_clause = catch_error(List.flatten(1)) end test "flunk" do "This should never be tested" = flunk rescue error in [ExUnit.AssertionError] -> "Flunked!" = error.message end test "flunk with message" do "This should never be tested" = flunk "This should raise an error" rescue error in [ExUnit.AssertionError] -> "This should raise an error" = error.message end test "flunk with wrong argument type" do "This should never be tested" = flunk ["flunk takes a binary, not a list"] rescue error -> "no function clause matching in ExUnit.Assertions.flunk/1" = FunctionClauseError.message error end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/callbacks_test.exs000066400000000000000000000114511254730255300254710ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.CallbacksTest do use ExUnit.Case import ExUnit.CaptureIO test "callbacks run custom code with context" do defmodule CallbacksTest do use ExUnit.Case setup_all do {:ok, [context: :setup_all]} end setup do {:ok, [initial_setup: true]} end setup context do assert context[:initial_setup] assert context[:context] == :setup_all {:ok, [context: :setup]} end test "callbacks", context do assert context[:context] == :setup end end assert capture_io(fn -> ExUnit.run end) =~ "1 test, 0 failures" end test "doesn't choke on setup errors" do defmodule SetupTest do use ExUnit.Case setup _ do :ok = error end test "ok" do :ok end defp error, do: :error end assert capture_io(fn -> ExUnit.run end) =~ "** (MatchError) no match of right hand side value: :error" end test "doesn't choke on setup_all errors" do defmodule SetupAllTest do use ExUnit.Case setup_all _ do :ok = error end test "ok" do :ok end defp error, do: :error end assert capture_io(fn -> ExUnit.run end) =~ "** (MatchError) no match of right hand side value: :error" end test "doesn't choke on on_exit errors" do defmodule OnExitErrorTest do use ExUnit.Case test "ok" do on_exit fn -> :ok = error end :ok end defp error, do: :error end assert capture_io(fn -> ExUnit.run end) =~ "** (MatchError) no match of right hand side value: :error" end test "doesn't choke when on_exit exits" do defmodule OnExitExitTest do use ExUnit.Case, async: false test "ok" do on_exit fn -> Process.exit(self(), :kill) end :ok end end assert capture_io(fn -> ExUnit.run end) =~ ">) killed" end defp no_formatters! do ExUnit.configure(formatters: []) on_exit fn -> ExUnit.configure(formatters: [ExUnit.CLIFormatter]) end end test "exits with shutdown reason" do defmodule OnExitAliveTest do use ExUnit.Case setup do parent = self() pid = spawn_link fn -> Process.flag(:trap_exit, true) send parent, :ready receive do {:EXIT, ^parent, :shutdown} -> receive do: ({:on_exit, pid} -> send pid, :done) end end receive do: (:ready -> :ok) on_exit fn -> send pid, {:on_exit, self} assert_receive :done IO.puts "on_exit run" end :ok end test "ok" do :ok end end output = capture_io(fn -> ExUnit.run end) assert output =~ "on_exit run" assert output =~ "1 test, 0 failures" end test "runs multiple on_exit exits and overrides by ref" do defmodule OnExitSuccessTest do use ExUnit.Case setup do on_exit fn -> IO.puts "on_exit setup run" end on_exit {:overridden, 1}, fn -> IO.puts "on_exit 1 overridden -> not run" end :ok end setup_all do on_exit fn -> IO.puts "on_exit setup_all run" end :ok end test "ok" do on_exit fn -> IO.puts "simple on_exit run" end on_exit {:overridden, 2}, fn -> IO.puts "on_exit 2 overridden -> not run" end on_exit {:overridden, 2}, fn -> IO.puts "on_exit 2 overrides -> run" end on_exit {:overridden, 1}, fn -> IO.puts "on_exit 1 overrides -> run" end :ok end end no_formatters! output = capture_io(fn -> ExUnit.run end) assert output =~ """ on_exit 2 overrides -> run simple on_exit run on_exit 1 overrides -> run on_exit setup run on_exit setup_all run """ refute output =~ "not run" end test "runs multiple on_exit on failure" do defmodule OnExitFailureTest do use ExUnit.Case setup do on_exit fn -> IO.puts "on_exit setup run" end :ok end setup_all do on_exit fn -> IO.puts "on_exit setup_all run" end :ok end test "ok" do on_exit fn -> IO.puts "simple on_exit run" end flunk "oops" end end no_formatters! output = capture_io(fn -> ExUnit.run end) assert output =~ """ simple on_exit run on_exit setup run on_exit setup_all run """ end end defmodule ExUnit.CallbacksNoTests do use ExUnit.Case, async: true setup_all do raise "Never run" end setup do raise "Never run" end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/capture_io_test.exs000066400000000000000000000201161254730255300257020ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.CaptureIOTest do use ExUnit.Case defmodule GetUntil do def until_new_line(_, :eof, _) do {:done, :eof, []} end def until_new_line(this_far, chars, stop_char) do case Enum.split_while(chars, fn(c) -> c != stop_char end) do {l, []} -> {:more, this_far ++ l} {l, [stop_char|rest]} -> {:done, this_far ++ l ++ [stop_char], rest} end end def get_line(device \\ Process.group_leader) do send device, {:io_request, self, device, {:get_until, :unicode, "", __MODULE__, :until_new_line, [?\n]}} receive do {:io_reply, _, data} -> data end end end import ExUnit.CaptureIO doctest ExUnit.CaptureIO, import: true test "no leakage on failures" do group_leader = Process.group_leader() test = self() assert_raise ArgumentError, fn -> capture_io(fn -> send(test, {:string_io, Process.group_leader()}) raise ArgumentError end) end receive do {:string_io, pid} -> ref = Process.monitor(pid) assert_receive {:DOWN, ^ref, _, _, _} end assert Process.group_leader() == group_leader end test "with no output" do assert capture_io(fn -> end) == "" end test "with put chars" do assert capture_io(fn -> :io.put_chars("") end) == "" assert capture_io(fn -> :io.put_chars("a") :io.put_chars("b") end) == "ab" assert capture_io(fn -> :io.put_chars("josé") end) == "josé" assert capture_io(fn -> spawn(fn -> :io.put_chars("a") end) :timer.sleep(10) end) == "a" assert capture_io(fn -> assert :io.put_chars("a") == :ok end) end test "with put chars to stderr" do assert capture_io(:stderr, fn -> :io.put_chars(:standard_error, "a") end) == "a" end test "with get chars" do assert capture_io(fn -> :io.get_chars(">", 3) end) == ">" assert capture_io([capture_prompt: false], fn -> :io.get_chars(">", 3) end) == "" capture_io(fn -> assert :io.get_chars(">", 3) == :eof end) capture_io("", fn -> assert :io.get_chars(">", 3) == :eof end) capture_io("abc\ndef", fn -> assert :io.get_chars(">", 3) == "abc" assert :io.get_chars(">", 5) == "\ndef" assert :io.get_chars(">", 7) == :eof end) capture_io("あいう", fn -> assert :io.get_chars(">", 2) == "あい" assert :io.get_chars(">", 1) == "う" assert :io.get_chars(">", 1) == :eof end) end test "with get line" do assert capture_io(fn -> :io.get_line ">" end) == ">" assert capture_io([capture_prompt: false], fn -> :io.get_line ">" end) == "" capture_io(fn -> assert :io.get_line(">") == :eof end) capture_io("", fn -> assert :io.get_line(">") == :eof end) capture_io("\n", fn -> assert :io.get_line(">") == "\n" assert :io.get_line(">") == :eof end) capture_io("a", fn -> assert :io.get_line(">") == "a" assert :io.get_line(">") == :eof end) capture_io("a\n", fn -> assert :io.get_line(">") == "a\n" assert :io.get_line(">") == :eof end) capture_io("a\nb", fn -> assert :io.get_line(">") == "a\n" assert :io.get_line(">") == "b" assert :io.get_line(">") == :eof end) capture_io("あい\nう", fn -> assert :io.get_line(">") == "あい\n" assert :io.get_line(">") == "う" assert :io.get_line(">") == :eof end) end test "with get password" do capture_io(fn -> assert :io.get_password() == :eof end) capture_io("", fn -> assert :io.get_password() == :eof end) capture_io("abc", fn -> assert :io.get_password() == "abc" assert :io.get_password() == :eof end) capture_io("abc\n", fn -> assert :io.get_password() == "abc\n" assert :io.get_password() == :eof end) capture_io("\n", fn -> assert :io.get_password() == "\n" assert :io.get_password() == :eof end) capture_io("a\nb", fn -> assert :io.get_password() == "a\n" assert :io.get_password() == "b" assert :io.get_password() == :eof end) capture_io("あい\nう", fn -> assert :io.get_password() == "あい\n" assert :io.get_password() == "う" assert :io.get_password() == :eof end) end test "with get until" do assert capture_io(fn -> :io.scan_erl_form('>') end) == ">" assert capture_io("1.\n", fn -> :io.scan_erl_form('>') end) == ">" assert capture_io("1\n.\n", fn -> :io.scan_erl_form('>') end) == ">>" assert capture_io([capture_prompt: false], fn -> :io.scan_erl_form('>') end) == "" capture_io(fn -> assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("1", fn -> assert :io.scan_erl_form('>') == {:ok, [{:integer, 1, 1}], 1} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("1\n.", fn -> assert :io.scan_erl_form('>') == {:ok, [{:integer, 1, 1}, {:dot, 2}], 2} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("1.\n.", fn -> assert :io.scan_erl_form('>') == {:ok, [{:integer, 1, 1}, {:dot, 1}], 2} assert :io.scan_erl_form('>') == {:ok, [dot: 1], 1} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("\"a", fn -> assert :io.scan_erl_form('>') == {:error, {1, :erl_scan, {:string, 34, 'a'}}, 1} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("\"a\n\"", fn -> assert :io.scan_erl_form('>') == {:ok, [{:string, 1, 'a\n'}], 2} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io(":erl. mof*,,l", fn -> assert :io.scan_erl_form('>') == {:ok, [{:":", 1}, {:atom, 1, :erl}, {:dot, 1}], 1} assert :io.scan_erl_form('>') == {:ok, [{:atom, 1, :mof}, {:*, 1}, {:",", 1}, {:",", 1}, {:atom, 1, :l}], 1} assert :io.scan_erl_form('>') == {:eof, 1} end) capture_io("a\nb\nc", fn -> assert GetUntil.get_line == "a\n" assert GetUntil.get_line == "b\n" assert GetUntil.get_line == :eof end) end test "with setopts" do assert capture_io(fn -> assert :io.setopts({:encoding, :latin1}) == {:error, :enotsup} end) == "" end test "with getopts" do assert capture_io(fn -> assert :io.getopts == {:ok, [binary: true, encoding: :unicode]} end) == "" end test "with columns" do assert capture_io(fn -> :io.columns end) == "" capture_io(fn -> assert :io.columns == {:error, :enotsup} end) end test "with rows" do assert capture_io(fn -> :io.rows end) == "" capture_io(fn -> assert :io.rows == {:error, :enotsup} end) end test "with multiple io requests" do assert capture_io(fn -> send_and_receive_io({:requests, [{:put_chars, :unicode, "a"}, {:put_chars, :unicode, "b"}]}) end) == "ab" capture_io(fn -> assert send_and_receive_io({:requests, [{:put_chars, :unicode, "a"}, {:put_chars, :unicode, "b"}]}) == :ok end) end test "with unknown io request" do assert capture_io(fn -> send_and_receive_io(:unknown) end) == "" capture_io(fn -> assert send_and_receive_io(:unknown) == {:error, :request} end) end test "with assert inside" do try do capture_io(fn -> assert false end) rescue error in [ExUnit.AssertionError] -> assert error.message == "Expected truthy, got false" end end test "capture :stderr by two processes" do spawn(fn -> capture_io(:stderr, fn -> :timer.sleep(100) end) end) :timer.sleep(10) assert_raise RuntimeError, "IO device registered at :standard_error is already captured", fn -> capture_io(:stderr, fn -> end) end :timer.sleep(100) end defp send_and_receive_io(req) do send :erlang.group_leader, {:io_request, self, self, req} s = self receive do {:io_reply, ^s, res} -> res end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/capture_log_test.exs000066400000000000000000000027611254730255300260620ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.CaptureLogTest do use ExUnit.Case require Logger import ExUnit.CaptureLog setup_all do :ok = Logger.remove_backend(:console) on_exit(fn -> Logger.add_backend(:console, flush: true) end) end test "no output" do assert capture_log(fn -> end) == "" end test "assert inside" do group_leader = Process.group_leader() try do capture_log(fn -> assert false end) rescue error in [ExUnit.AssertionError] -> assert error.message == "Expected truthy, got false" end # Ensure no leakage on failures assert group_leader == Process.group_leader() refute_received {:gen_event_EXIT, _, _} end test "level aware" do assert capture_log([level: :warn], fn -> Logger.info "here" end) == "" end test "log tracking" do logged = assert capture_log(fn -> Logger.info "one" logged = capture_log(fn -> Logger.error "one" end) send(test = self(), {:nested, logged}) Logger.warn "two" spawn(fn -> Logger.debug "three" send(test, :done) end) receive do: (:done -> :ok) end) assert logged =~ "[info] one\n" assert logged =~ "[warn] two\n" assert logged =~ "[debug] three\n" assert logged =~ "[error] one\n" receive do {:nested, logged} -> assert logged =~ "[error] one\n" refute logged =~ "[warn] two\n" end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/case_template_test.exs000066400000000000000000000021711254730255300263570ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.SampleCase do use ExUnit.CaseTemplate using _ do quote do import unquote(__MODULE__) end end def hello do "world" end setup_all do {:ok, [context: :setup_all, setup_all: 1]} end setup context do assert context[:context] == :setup_all {:ok, [context: :setup, setup: 1]} end end defmodule ExUnit.NestedCase do use ExUnit.CaseTemplate setup_all context do {:ok, [setup_all: context[:setup_all] + 1]} end setup context do {:ok, [setup: context[:setup] + 1]} end end defmodule ExUnit.CaseTemplateTest do use ExUnit.SampleCase, async: true use ExUnit.NestedCase two = 2 test "unquoting the value #{two}" do assert 2 == unquote(two) end test "receives context from parent case", %{context: context} do assert context == :setup end test "runs both templates setup", context do assert context[:setup] == 2 end test "runs both templates setup all", context do assert context[:setup_all] == 2 end test "using code is executed" do assert hello() == "world" end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/case_test.exs000066400000000000000000000017271254730255300244720ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.CaseTest do use ExUnit.Case, async: true @moduletag :moduletag test "defines test case info" do assert %ExUnit.TestCase{name: __MODULE__, tests: tests} = __ex_unit__(:case) assert length(tests) > 0 end @tag hello: false @tag :hello @tag world: :bad @tag world: :good test "tags", context do line = __ENV__.line - 1 assert context[:case] == __MODULE__ assert context[:test] == __ENV__.function |> elem(0) assert context[:line] == line assert context[:async] == true assert context[:hello] == true assert context[:world] == :good end test "reset tags", context do assert is_nil(context[:hello]) assert is_nil(context[:world]) end test "module tags", context do assert context[:moduletag] == true end @tag moduletag: :overridden test "module tags can be overridden", context do assert context[:moduletag] == :overridden end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/doc_test_test.exs000066400000000000000000000216231254730255300253600ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ import ExUnit.TestHelpers defmodule ExUnit.DocTestTest.GoodModule do @doc """ iex> test_fun 1 iex> test_fun + 1 2 """ def test_fun, do: 1 @doc ~S""" iex> ~S(f#{o}o) "f\#{o}o" """ def test_sigil, do: :ok @doc """ iex> a = 1 iex> b = a + 2 3 iex> a + b 4 """ def single_context, do: :ok @doc """ iex> 1 + (fn() -> "" end).() ** (ArithmeticError) bad argument in arithmetic expression iex> 2 + (fn() -> :a end).() ** (ArithmeticError) bad argument in arithmetic expression """ def two_exceptions, do: :ok @doc """ iex> 1 + (fn() -> :a end).() ** (ArithmeticError) bad argument in arithmetic expression """ def exception_test, do: :ok @doc """ iex> Enum.into([a: 0, b: 1, c: 2], HashDict.new) #HashDict<[c: 2, b: 1, a: 0]> """ def inspect1_test, do: :ok @doc """ iex> x = Enum.into([a: 0, b: 1, c: 2], HashDict.new) ...> x #HashDict<[c: 2, b: 1, a: 0]> """ def inspect2_test, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.MultipleExceptions do @doc """ iex> 1 + "" ** (ArithmeticError) bad argument in arithmetic expression iex> 2 + "" ** (ArithmeticError) bad argument in arithmetic expression """ def two_exceptions, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.SomewhatGoodModuleWithOnly do @doc """ iex> test_fun 1 iex> test_fun + 1 2 """ def test_fun, do: 1 @doc """ iex> test_fun 1 iex> test_fun + 1 1 """ def test_fun1, do: 1 end |> write_beam defmodule ExUnit.DocTestTest.SomewhatGoodModuleWithExcept do @moduledoc """ iex> 1 + 1 1 """ @doc """ iex> test_fun 1 iex> test_fun + 1 2 """ def test_fun, do: 1 @doc """ iex> test_fun 1 iex> test_fun + 1 1 """ def test_fun1, do: 1 end |> write_beam defmodule ExUnit.DocTestTest.NoImport do @doc """ iex> ExUnit.DocTestTest.NoImport.min(1, 2) 2 """ def min(a, b), do: max(a, b) end |> write_beam defmodule ExUnit.DocTestTest.Invalid do @moduledoc """ iex> 1 + * 1 1 iex> 1 + hd(List.flatten([1])) 3 iex> :oops #HashDict<[]> iex> Hello.world :world iex> raise "oops" ** (WhatIsThis) oops iex> raise "oops" ** (RuntimeError) hello """ end |> write_beam defmodule ExUnit.DocTestTest.IndentationHeredocs do @doc ~S''' Receives a test and formats its failure. ## Examples iex> " 1\n 2\n" """ 1 2 """ ''' def heredocs, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.IndentationMismatchedPrompt do @doc ~S''' iex> foo = 1 iex> bar = 2 iex> foo + bar 3 ''' def mismatched, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.IndentationTooMuch do @doc ~S''' iex> 1 + 2 3 ''' def too_much, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.IndentationNotEnough do @doc ~S''' iex> 1 + 2 3 ''' def not_enough, do: :ok end |> write_beam defmodule ExUnit.DocTestTest.Incomplete do @doc ~S''' iex> 1 + 2 ''' def not_enough, do: :ok end |> write_beam defmodule ExUnit.DocTestTest do use ExUnit.Case # This is intentional. The doctests in DocTest's docs # fail for demonstration purposes. # doctest ExUnit.DocTest doctest ExUnit.DocTestTest.GoodModule, import: true doctest ExUnit.DocTestTest.SomewhatGoodModuleWithOnly, only: [test_fun: 0], import: true doctest ExUnit.DocTestTest.SomewhatGoodModuleWithExcept, except: [:moduledoc, test_fun1: 0], import: true doctest ExUnit.DocTestTest.NoImport doctest ExUnit.DocTestTest.IndentationHeredocs import ExUnit.CaptureIO test "multiple functions filtered with :only" do defmodule MultipleOnly do use ExUnit.Case doctest ExUnit.DocTestTest.SomewhatGoodModuleWithOnly, only: [test_fun: 0, test_fun1: 0], import: true end assert capture_io(fn -> ExUnit.run end) =~ "2 tests, 1 failure" end test "doctest failures" do defmodule ActuallyCompiled do use ExUnit.Case doctest ExUnit.DocTestTest.Invalid end ExUnit.configure(seed: 0, colors: [enabled: false]) output = capture_io(fn -> ExUnit.run end) # Test order is not guaranteed, we can't match this as a string for each failing doctest assert output =~ ~r/\d+\) test moduledoc at ExUnit\.DocTestTest\.Invalid \(\d+\) \(ExUnit\.DocTestTest\.ActuallyCompiled\)/ assert output =~ """ 1) test moduledoc at ExUnit.DocTestTest.Invalid (1) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest did not compile, got: (SyntaxError) test/ex_unit/doc_test_test.exs:117: syntax error before: '*' code: 1 + * 1 stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ assert output =~ """ 2) test moduledoc at ExUnit.DocTestTest.Invalid (2) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest failed code: 1 + hd(List.flatten([1])) === 3 lhs: 2 stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ assert output =~ """ 3) test moduledoc at ExUnit.DocTestTest.Invalid (3) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest failed code: inspect(:oops) === "#HashDict<[]>" lhs: ":oops" stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ assert output =~ """ 4) test moduledoc at ExUnit.DocTestTest.Invalid (4) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest failed: got UndefinedFunctionError with message undefined function: Hello.world/0 (module Hello is not available) code: Hello.world stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ assert output =~ """ 5) test moduledoc at ExUnit.DocTestTest.Invalid (5) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest failed: expected exception WhatIsThis with message "oops" but got RuntimeError with message "oops" code: raise "oops" stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ assert output =~ """ 6) test moduledoc at ExUnit.DocTestTest.Invalid (6) (ExUnit.DocTestTest.ActuallyCompiled) test/ex_unit/doc_test_test.exs:218 Doctest failed: expected exception RuntimeError with message "hello" but got RuntimeError with message "oops" code: raise "oops" stacktrace: test/ex_unit/doc_test_test.exs:117: ExUnit.DocTestTest.Invalid (module) """ end test "tags tests as doctests" do defmodule DoctestTag do use ExUnit.Case doctest ExUnit.DocTestTest.NoImport setup test do assert test.doctest :ok end end assert capture_io(fn -> ExUnit.run end) =~ "1 test, 0 failures" end test "multiple exceptions in one test case is not supported" do assert_raise ExUnit.DocTest.Error, ~r"multiple exceptions in one doctest case are not supported", fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.MultipleExceptions end end end test "fails on invalid module" do assert_raise CompileError, ~r"module ExUnit.DocTestTest.Unknown is not loaded and could not be found", fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.Unknown end end end test "fails when there are no docs" do assert_raise ExUnit.DocTest.Error, ~r"could not retrieve the documentation for module ExUnit.DocTestTest", fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest end end end test "fails in indentation mismatch" do assert_raise ExUnit.DocTest.Error, ~r/indentation level mismatch: " iex> bar = 2", should have been 2 spaces/, fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.IndentationMismatchedPrompt end end assert_raise ExUnit.DocTest.Error, ~r/indentation level mismatch: " 3", should have been 2 spaces/, fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.IndentationTooMuch end end assert_raise ExUnit.DocTest.Error, ~r/indentation level mismatch: \" 3\", should have been 4 spaces/, fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.IndentationNotEnough end end assert_raise ExUnit.DocTest.Error, ~r/expected non-blank line to follow iex> prompt/, fn -> defmodule NeverCompiled do import ExUnit.DocTest doctest ExUnit.DocTestTest.Incomplete end end end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/filters_test.exs000066400000000000000000000063761254730255300252340ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.FiltersTest do use ExUnit.Case, async: true doctest ExUnit.Filters test "evaluating filters" do assert ExUnit.Filters.eval([], [:os], %{}, []) == :ok assert ExUnit.Filters.eval([], [os: :win], %{os: :unix}, []) == :ok assert ExUnit.Filters.eval([], [:os], %{os: :unix}, []) == {:error, :os} assert ExUnit.Filters.eval([], [os: :unix], %{os: :unix}, []) == {:error, :os} assert ExUnit.Filters.eval([os: :win], [], %{}, []) == :ok assert ExUnit.Filters.eval([os: :win], [], %{os: :unix}, []) == :ok assert ExUnit.Filters.eval([os: :win], [:os], %{}, []) == :ok assert ExUnit.Filters.eval([os: :win], [:os], %{os: :win}, []) == :ok assert ExUnit.Filters.eval([os: :win, os: :unix], [:os], %{os: :win}, []) == :ok end test "evaluating filters matches integers" do assert ExUnit.Filters.eval([int: "1"], [], %{int: 1}, []) == :ok assert ExUnit.Filters.eval([int: "1"], [int: 5], %{int: 1}, []) == :ok assert ExUnit.Filters.eval([int: "1"], [:int], %{int: 1}, []) == :ok end test "evaluating filter matches atoms" do assert ExUnit.Filters.eval([os: "win"], [], %{os: :win}, []) == :ok assert ExUnit.Filters.eval([os: "win"], [os: :unix], %{os: :win}, []) == :ok assert ExUnit.Filters.eval([os: "win"], [:os], %{os: :win}, []) == :ok assert ExUnit.Filters.eval([case: "Foo"], [:os], %{case: Foo}, []) == :ok end test "evaluating filter matches regexes" do assert ExUnit.Filters.eval([os: ~r"win"], [], %{os: :win}, []) == :ok assert ExUnit.Filters.eval([os: ~r"mac"], [os: :unix], %{os: :unix}, []) == {:error, :os} end test "evaluating filter uses special rules for line" do tests = [%ExUnit.Test{tags: %{line: 3}}, %ExUnit.Test{tags: %{line: 5}}] assert ExUnit.Filters.eval([line: 3], [:line], %{line: 3}, tests) == :ok assert ExUnit.Filters.eval([line: 4], [:line], %{line: 3}, tests) == :ok assert ExUnit.Filters.eval([line: 2], [:line], %{line: 3}, tests) == {:error, :line} assert ExUnit.Filters.eval([line: 5], [:line], %{line: 3}, tests) == {:error, :line} end test "parsing filters" do assert ExUnit.Filters.parse(["run"]) == [:run] assert ExUnit.Filters.parse(["run:true"]) == [run: "true"] assert ExUnit.Filters.parse(["run:test"]) == [run: "test"] assert ExUnit.Filters.parse(["line:9"]) == [line: "9"] end test "file paths with line numbers" do assert ExUnit.Filters.parse_path("test/some/path.exs:123") == {"test/some/path.exs", [exclude: [:test], include: [line: "123"]]} assert ExUnit.Filters.parse_path("test/some/path.exs") == {"test/some/path.exs", []} assert ExUnit.Filters.parse_path("test/some/path.exs:123notreallyalinenumber123") == {"test/some/path.exs:123notreallyalinenumber123", []} assert ExUnit.Filters.parse_path("C:\\some\\path.exs:123") == {"C:\\some\\path.exs", [exclude: [:test], include: [line: "123"]]} assert ExUnit.Filters.parse_path("C:\\some\\path.exs") == {"C:\\some\\path.exs", []} assert ExUnit.Filters.parse_path("C:\\some\\path.exs:123notreallyalinenumber123") == {"C:\\some\\path.exs:123notreallyalinenumber123", []} end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/formatter_test.exs000066400000000000000000000134621254730255300255610ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.FormatterTest do use ExUnit.Case, async: true import ExUnit.Formatter doctest ExUnit.Formatter def falsy, do: false def formatter(_color, msg), do: msg defmacrop catch_assertion(expr) do quote do try do unquote(expr) rescue e -> e end end end defp case do %ExUnit.TestCase{name: Hello} end defp test do %ExUnit.Test{name: :world, case: Hello, tags: [file: __ENV__.file, line: 1]} end test "formats test case filters" do filters = [run: true, slow: false] assert format_filters(filters, :include) =~ "Including tags: [run: true, slow: false]" assert format_filters(filters, :exclude) =~ "Excluding tags: [run: true, slow: false]" end test "formats test errors" do failure = {:error, catch_error(raise "oops"), []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (RuntimeError) oops """ end test "formats test exits" do failure = {:exit, 1, []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (exit) 1 """ end test "formats test exits with mfa" do failure = {:exit, {:bye, {:m, :f, []}}, []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (exit) exited in: :m.f() ** (EXIT) :bye """ end test "formats test throws" do failure = {:throw, 1, []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (throw) 1 """ end test "formats test EXITs" do failure = {{:EXIT, self}, 1, []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (EXIT from #{inspect self}) 1 """ end test "formats stacktraces" do failure = {:error, catch_error(raise "oops"), [{Oops, :wrong, 1, [file: "formatter_test.exs", line: 1]}]} assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (RuntimeError) oops stacktrace: formatter_test.exs:1: Oops.wrong/1 """ end test "formats assertions" do failure = {:error, catch_assertion(assert ExUnit.FormatterTest.falsy), []} assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 Expected truthy, got false code: ExUnit.FormatterTest.falsy() """ end test "formats test case errors" do failure = {:error, catch_error(raise "oops"), []} assert format_test_case_failure(case(), failure, 1, 80, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated ** (RuntimeError) oops """ end test "formats assertions with operators with no limit" do failure = {:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []} assert format_test_case_failure(case(), failure, 1, :infinity, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Assertion with == failed code: [1, 2, 3] == [4, 5, 6] lhs: [1, 2, 3] rhs: [4, 5, 6] """ end test "formats assertions with operators with column limit" do failure = {:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []} assert format_test_case_failure(case(), failure, 1, 15, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Assertion with == failed code: [1, 2, 3] == [4, 5, 6] lhs: [1, 2, 3] rhs: [4, 5, 6] """ end test "formats assertions with message with multiple lines" do message = "Some meaningful error:\nuseful info\nanother useful info" failure = {:error, catch_assertion(assert(false, message)), []} assert format_test_case_failure(case(), failure, 1, :infinity, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Some meaningful error: useful info another useful info """ end defmodule BadInspect do defstruct key: 0 defimpl Inspect do def inspect(struct, opts) when is_atom(opts) do struct.unknown end end end test "inspect failure" do failure = {:error, catch_assertion(assert :will_fail == %BadInspect{}), []} message = "got FunctionClauseError with message `no function clause matching " <> "in Inspect.ExUnit.FormatterTest.BadInspect.inspect/2` while inspecting " <> "%{__struct__: ExUnit.FormatterTest.BadInspect, key: 0}" assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 Assertion with == failed code: :will_fail == %BadInspect{} lhs: :will_fail rhs: %Inspect.Error{message: \"#{message}\"} """ end defmodule BadMessage do defexception key: 0 def message(_message) do raise "oops" end end test "message failure" do failure = {:error, catch_error(raise BadMessage), []} message = "got RuntimeError with message `oops` while retrieving Exception.message/1 " <> "for %ExUnit.FormatterTest.BadMessage{key: 0}" assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 ** (ExUnit.FormatterTest.BadMessage) #{message} """ end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit/runner_test.exs000066400000000000000000000013041254730255300250570ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule ExUnit.RunnerTest do use ExUnit.Case test "it sets max cases to one with trace enabled" do opts = Keyword.merge(ExUnit.configuration, trace: true) {_, config} = ExUnit.Runner.configure(opts) assert config.trace assert config.timeout == 60_000 assert config.max_cases == 1 end test "it does not set timeout to infinity and the max cases to 1 with trace disabled" do opts = Keyword.merge(ExUnit.configuration, trace: false) {_, config} = ExUnit.Runner.configure(opts) refute config.trace assert config.max_cases == :erlang.system_info(:schedulers_online) assert config.timeout == 60_000 end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/ex_unit_test.exs000066400000000000000000000115371254730255300235570ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule ExUnitTest do use ExUnit.Case import ExUnit.CaptureIO test "it supports many runs" do defmodule SampleTest do use ExUnit.Case, async: false test "true" do assert false end test "false" do assert false end end assert capture_io(fn -> assert ExUnit.run == %{failures: 2, skipped: 0, total: 2} end) =~ "2 tests, 2 failures" end test "it doesn't hang on exists" do defmodule EventServerTest do use ExUnit.Case, async: false test "spawn and crash" do spawn_link(fn -> exit :foo end) receive after: (1000 -> :ok) end end assert capture_io(fn -> assert ExUnit.run == %{failures: 1, skipped: 0, total: 1} end) =~ "1 test, 1 failure" end test "it supports timeouts" do defmodule TimeoutTest do use ExUnit.Case @tag timeout: 10 test "ok" do :timer.sleep(:infinity) end end output = capture_io(fn -> ExUnit.run end) assert output =~ "** (ExUnit.TimeoutError) test timed out after 10ms" assert output =~ ~r"\(stdlib\) timer\.erl:\d+: :timer\.sleep/1" end test "it supports configured timeout" do defmodule ConfiguredTimeoutTest do use ExUnit.Case test "ok" do :timer.sleep(:infinity) end end ExUnit.configure(timeout: 5) output = capture_io(fn -> ExUnit.run end) assert output =~ "** (ExUnit.TimeoutError) test timed out after 5ms" after ExUnit.configure(timeout: 60_000) end test "filtering cases with tags" do defmodule ParityTest do use ExUnit.Case test "zero", do: :ok @tag even: false test "one", do: :ok @tag even: true test "two", do: assert 1 == 2 @tag even: false test "three", do: :ok end test_cases = ExUnit.Server.start_run {result, output} = run_with_filter([], test_cases) assert result == %{failures: 1, skipped: 0, total: 4} assert output =~ "4 tests, 1 failure" {result, output} = run_with_filter([exclude: [even: true]], test_cases) assert result == %{failures: 0, skipped: 1, total: 4} assert output =~ "4 tests, 0 failures, 1 skipped" {result, output} = run_with_filter([exclude: :even], test_cases) assert result == %{failures: 0, skipped: 3, total: 4} assert output =~ "4 tests, 0 failures, 3 skipped" {result, output} = run_with_filter([exclude: :even, include: [even: true]], test_cases) assert result == %{failures: 1, skipped: 2, total: 4} assert output =~ "4 tests, 1 failure, 2 skipped" {result, output} = run_with_filter([exclude: :test, include: [even: true]], test_cases) assert result == %{failures: 1, skipped: 3, total: 4} assert output =~ "4 tests, 1 failure, 3 skipped" end test "log capturing" do defmodule LogCapturingTest do use ExUnit.Case require Logger setup_all do :ok = Logger.remove_backend(:console) on_exit(fn -> Logger.add_backend(:console, flush: true) end) end @tag :capture_log test "one" do Logger.debug("one") assert 1 == 1 end @tag :capture_log test "two" do Logger.debug("two") assert 1 == 2 end @tag capture_log: [] test "three" do Logger.debug("three") assert 1 == 2 end test "four" do Logger.debug("four") assert 1 == 2 end end output = capture_io(&ExUnit.run/0) assert output =~ "[debug] two" refute output =~ "[debug] one" assert output =~ "[debug] three" refute output =~ "[debug] four" end test "it registers only the first test with any given name" do capture_io :stderr, fn -> defmodule TestWithSameNames do use ExUnit.Case, async: false test "same name, different outcome" do assert 1 == 1 end test "same name, different outcome" do assert 1 == 2 end end end assert capture_io(fn -> assert ExUnit.run == %{failures: 0, skipped: 0, total: 1} end) =~ "1 test, 0 failure" end test "it produces error on not implemented tests" do defmodule TestNotImplemented do use ExUnit.Case, async: false setup context do assert context[:not_implemented] :ok end test "this is not implemented yet" end output = capture_io(fn -> assert ExUnit.run == %{failures: 1, skipped: 0, total: 1} end) assert output =~ "Not yet implemented" assert output =~ "1 test, 1 failure" end defp run_with_filter(filters, {async, sync, load_us}) do opts = Keyword.merge(ExUnit.configuration, filters) output = capture_io fn -> Process.put(:capture_result, ExUnit.Runner.run(async, sync, opts, load_us)) end {Process.get(:capture_result), output} end end elixir-lang-1.1.0~0.20150708/lib/ex_unit/test/test_helper.exs000066400000000000000000000007071254730255300233600ustar00rootroot00000000000000Logger.configure_backend(:console, colors: [enabled: false]) ExUnit.start [trace: "--trace" in System.argv] # Beam files compiled on demand path = Path.expand("../tmp/beams", __DIR__) File.rm_rf!(path) File.mkdir_p!(path) Code.prepend_path(path) defmodule ExUnit.TestHelpers do def write_beam({:module, name, bin, _} = res) do beam_path = Path.join(unquote(path), Atom.to_string(name) <> ".beam") File.write!(beam_path, bin) res end end elixir-lang-1.1.0~0.20150708/lib/iex/000077500000000000000000000000001254730255300164505ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/iex/lib/000077500000000000000000000000001254730255300172165ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex.ex000066400000000000000000000344531254730255300203520ustar00rootroot00000000000000defmodule IEx do @moduledoc ~S""" Elixir's interactive shell. This module is the main entry point for Interactive Elixir and in this documentation we will talk a bit about how IEx works. Notice that some of the functionalities described here will not be available depending on your terminal. In particular, if you get a message saying that the smart terminal could not be run, some of the features described here won't work. ## Helpers IEx provides a bunch of helpers. They can be accessed by typing `h()` into the shell or as a documentation for the `IEx.Helpers` module. ## The Break command Inside IEx, hitting `Ctrl+C` will open up the `BREAK` menu. In this menu you can quit the shell, see process and ets tables information and much more. ## The User Switch command Besides the break command, one can type `Ctrl+G` to get to the user switch command menu. When reached, you can type `h` to get more information. In this menu, developers are able to start new shells and alternate between them. Let's give it a try: User switch command --> s 'Elixir.IEx' --> c The command above will start a new shell and connect to it. Create a new variable called `hello` and assign some value to it: hello = :world Now, let's roll back to the first shell: User switch command --> c 1 Now, try to access the `hello` variable again: hello ** (UndefinedFunctionError) undefined function: hello/0 The command above fails because we have switched shells. Since shells are isolated from each other, you can't access the variables defined in one shell from the other one. The user switch command menu also allows developers to connect to remote shells using the `r` command. A topic which we will discuss next. ## Remote shells IEx allows you to connect to another node in two fashions. First of all, we can only connect to a shell if we give names both to the current shell and the shell we want to connect to. Let's give it a try. First start a new shell: $ iex --sname foo iex(foo@HOST)1> The string between the parentheses in the prompt is the name of your node. We can retrieve it by calling the `node()` function: iex(foo@HOST)1> node() :"foo@HOST" iex(foo@HOST)2> Node.alive?() true For fun, let's define a simple module in this shell too: iex(foo@HOST)3> defmodule Hello do ...(foo@HOST)3> def world, do: "it works!" ...(foo@HOST)3> end Now, let's start another shell, giving it a name as well: $ iex --sname bar iex(bar@HOST)1> If we try to dispatch to `Hello.world`, it won't be available as it was defined only in the other shell: iex(bar@HOST)1> Hello.world ** (UndefinedFunctionError) undefined function: Hello.world/0 However, we can connect to the other shell remotely. Open up the User Switch prompt (Ctrl+G) and type: User switch command --> r 'foo@HOST' 'Elixir.IEx' --> c Now we are connected into the remote node, as the prompt shows us, and we can access the information and modules defined over there: rem(foo@macbook)1> Hello.world "it works" In fact, connecting to remote shells is so common that we provide a shortcut via the command line as well: $ iex --sname baz --remsh foo@HOST Where "remsh" means "remote shell". In general, Elixir supports: * remsh from an elixir node to an elixir node * remsh from a plain erlang node to an elixir node (through the ^G menu) * remsh from an elixir node to a plain erlang node (and get an erl shell there) Connecting an Elixir shell to a remote node without Elixir is **not** supported. ## The .iex.exs file When starting IEx, it will look for a local `.iex.exs` file (located in the current working directory), then a global one (located at `~/.iex.exs`) and will load the first one it finds (if any). The code in the chosen .iex.exs file will be evaluated in the shell's context. So, for instance, any modules that are loaded or variables that are bound in the .iex.exs file will be available in the shell after it has booted. Sample contents of a local .iex.exs file: # source another `.iex.exs` file import_file "~/.iex.exs" # print something before the shell starts IO.puts "hello world" # bind a variable that'll be accessible in the shell value = 13 Running the shell in the directory where the above .iex.exs file is located results in: $ iex Erlang 17 [...] hello world Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help) iex(1)> value 13 It is possible to load another file by supplying the `--dot-iex` option to iex. See `iex --help`. ## Configuring the shell There are a number of customization options provided by the shell. Take a look at the docs for the `IEx.configure/1` function by typing `h IEx.configure/1`. Those options can be configured in your project configuration file or globally by calling `IEx.configure/1` from your `~/.iex.exs` file like this: # .iex.exs IEx.configure(inspect: [limit: 3]) ### now run the shell ### $ iex Erlang 17 (erts-5.10.1) [...] Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help) iex(1)> [1, 2, 3, 4, 5] [1, 2, 3, ...] ## Expressions in IEx As an interactive shell, IEx evaluates expressions. This has some interesting consequences that are worth discussing. The first one is that the code is truly evaluated and not compiled. This means that any benchmarking done in the shell is going to have skewed results. So never run any profiling nor benchmarks in the shell. Second, IEx allows you to break an expression into many lines, since this is common in Elixir. For example: iex(1)> "ab ...(1)> c" "ab\nc" In the example above, the shell will be expecting more input until it finds the closing quote. Sometimes it is not obvious which character the shell is expecting, and the user may find themselves trapped in the state of incomplete expression with no ability to terminate it other than by exiting the shell. For such cases, there is a special break-trigger (`#iex:break`) that when encountered on a line by itself will force the shell to break out of any pending expression and return to its normal state: iex(1)> ["ab ...(1)> c" ...(1)> " ...(1)> ] ...(1)> #iex:break ** (TokenMissingError) iex:1: incomplete expression """ @doc """ Configures IEx. The supported options are: `:colors`, `:inspect`, `:default_prompt`, `:alive_prompt` and `:history_size`. ## Colors A keyword list that encapsulates all color settings used by the shell. See documentation for the `IO.ANSI` module for the list of supported colors and attributes. The value is a keyword list. List of supported keys: * `:enabled` - boolean value that allows for switching the coloring on and off * `:eval_result` - color for an expression's resulting value * `:eval_info` - … various informational messages * `:eval_error` - … error messages * `:stack_app` - … the app in stack traces * `:stack_info` - … the remaining info in stacktraces * `:ls_directory` - … for directory entries (ls helper) * `:ls_device` - … device entries (ls helper) When printing documentation, IEx will convert the markdown documentation to ANSI as well. Those can be configured via: * `:doc_code` — the attributes for code blocks (cyan, bright) * `:doc_inline_code` - inline code (cyan) * `:doc_headings` - h1 and h2 (yellow, bright) * `:doc_title` — the overall heading for the output (reverse, yellow, bright) * `:doc_bold` - (bright) * `:doc_underline` - (underline) ## Inspect A keyword list containing inspect options used by the shell when printing results of expression evaluation. Default to pretty formatting with a limit of 50 entries. See `Inspect.Opts` for the full list of options. ## History size Number of expressions and their results to keep in the history. The value is an integer. When it is negative, the history is unlimited. ## Prompt This is an option determining the prompt displayed to the user when awaiting input. The value is a keyword list. Two prompt types: * `:default_prompt` - used when `Node.alive?` returns `false` * `:alive_prompt` - used when `Node.alive?` returns `true` The part of the listed in the following of the prompt string is replaced. * `%counter` - the index of the history * `%prefix` - a prefix given by `IEx.Server` * `%node` - the name of the local node """ def configure(options) do IEx.Config.configure(options) end @doc """ Returns IEx configuration. """ def configuration do IEx.Config.configuration() end @doc """ Registers a function to be invoked after the IEx process is spawned. """ def after_spawn(fun) when is_function(fun) do IEx.Config.after_spawn(fun) end @doc """ Returns registered `after_spawn` callbacks. """ def after_spawn do IEx.Config.after_spawn() end @doc """ Returns `true` if IEx was started. """ def started? do IEx.Config.started?() end @doc """ Returns `string` escaped using the specified `color`. ANSI escapes in `string` are not processed in any way. """ def color(color, string) do case IEx.Config.color(color) do nil -> string ansi -> IO.iodata_to_binary([IO.ANSI.format_fragment(ansi, true), string | IO.ANSI.reset]) end end @doc """ Gets the IEx width for printing. Used by helpers and it has a maximum cap of 80 chars. """ def width do IEx.Config.width() end @doc """ Gets the options used for inspecting. """ def inspect_opts do IEx.Config.inspect_opts() end @doc """ Pries into the process environment. This is useful for debugging a particular chunk of code and inspect the state of a particular process. The process is temporarily changed to trap exits (i.e. the process flag `:trap_exit` is set to `true`) and has the `group_leader` changed to support ANSI escape codes. Those values are reverted by calling `respawn`, which starts a new IEx shell, freeing up the pried one. When a process is pried, all code runs inside IEx and, as such, it is evaluated and cannot access private functions of the module being pried. Module functions still need to be accessed via `Mod.fun(args)`. ## Examples Let's suppose you want to investigate what is happening with some particular function. By invoking `IEx.pry` from the function, IEx will allow you to access its binding (variables), verify its lexical information and access the process information. Let's see an example: import Enum, only: [map: 2] require IEx defmodule Adder do def add(a, b) do c = a + b IEx.pry end end When invoking `Adder.add(1, 2)`, you will receive a message in your shell to pry the given environment. By allowing it, the shell will be reset and you gain access to all variables and the lexical scope from above: pry(1)> map([a, b, c], &IO.inspect(&1)) 1 2 3 Keep in mind that `IEx.pry` runs in the caller process, blocking the caller during the evaluation cycle. The caller process can be freed by calling `respawn`, which starts a new IEx evaluation cycle, letting this one go: pry(2)> respawn true Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help) Setting variables or importing modules in IEx does not affect the caller the environment (hence it is called `pry`). """ defmacro pry(timeout \\ 5000) do quote do IEx.pry(binding, __ENV__, unquote(timeout)) end end @doc """ Callback for `IEx.pry/1`. You can invoke this function directly when you are not able to invoke `IEx.pry/1` as a macro. This function expects the binding (from `Kernel.binding/0`), the environment (from `__ENV__`) and the timeout (a sensible default is 5000). """ def pry(binding, env, timeout) do meta = "#{inspect self} at #{Path.relative_to_cwd(env.file)}:#{env.line}" opts = [binding: binding, dot_iex_path: "", env: env, prefix: "pry"] res = IEx.Server.take_over("Request to pry #{meta}", opts, timeout) # We cannot use colors because IEx may be off. case res do {:error, :self} -> IO.puts :stdio, "IEx cannot pry the shell itself." {:error, :no_iex} -> extra = case :os.type do {:win32, _} -> " If you are Windows, you may need to start IEx with the --werl flag." _ -> "" end IO.puts :stdio, "Cannot pry #{meta}. Is an IEx shell running?" <> extra _ -> :ok end res end ## Callbacks # This is a callback invoked by Erlang shell utilities # when someone press Ctrl+G and adds 's Elixir.IEx'. @doc false def start(opts \\ [], mfa \\ {IEx, :dont_display_result, []}) do spawn fn -> case :init.notify_when_started(self()) do :started -> :ok _ -> :init.wait_until_started() end :ok = start_iex() :ok = set_expand_fun() :ok = run_after_spawn() IEx.Server.start(opts, mfa) end end @doc false def dont_display_result, do: :"do not show this result in output" ## Helpers defp start_iex() do {:ok, _} = Application.ensure_all_started(:iex) :ok end defp set_expand_fun do gl = Process.group_leader glnode = node gl expand_fun = if glnode != node do _ = ensure_module_exists glnode, IEx.Remsh IEx.Remsh.expand node else &IEx.Autocomplete.expand(&1) end # expand_fun is not supported by a shell variant # on Windows, so we do two io calls, not caring # about the result of the expand_fun one. _ = :io.setopts(gl, expand_fun: expand_fun) :io.setopts(gl, binary: true, encoding: :unicode) end defp ensure_module_exists(node, mod) do unless :rpc.call node, :code, :is_loaded, [mod] do {m, b, f} = :code.get_object_code mod {:module, _} = :rpc.call node, :code, :load_binary, [m, f, b] end end defp run_after_spawn do _ = for fun <- Enum.reverse(after_spawn), do: fun.() :ok end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/000077500000000000000000000000001254730255300200035ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/app.ex000066400000000000000000000007501254730255300211230ustar00rootroot00000000000000defmodule IEx.App do @moduledoc false use Application def start(_type, _args) do import Supervisor.Spec children = [worker(IEx.Config, [])] options = [strategy: :one_for_one, name: IEx.Supervisor] tab = IEx.Config.new() case Supervisor.start_link(children, options) do {:ok, pid} -> {:ok, pid, tab} {:error, _} = error -> IEx.Config.delete(tab) error end end def stop(tab) do IEx.Config.delete(tab) end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/autocomplete.ex000066400000000000000000000173111254730255300230450ustar00rootroot00000000000000defmodule IEx.Autocomplete do @moduledoc false def expand('') do expand_import("") end def expand([h|t]=expr) do cond do h === ?. and t != []-> expand_dot(reduce(t)) h === ?: -> expand_erlang_modules() identifier?(h) -> expand_expr(reduce(expr)) (h == ?/) and t != [] and identifier?(hd(t)) -> expand_expr(reduce(t)) h in '([{' -> expand('') true -> no() end end defp identifier?(h) do (h in ?a..?z) or (h in ?A..?Z) or (h in ?0..?9) or h in [?_, ??, ?!] end defp expand_dot(expr) do case Code.string_to_quoted expr do {:ok, atom} when is_atom(atom) -> expand_call(atom, "") {:ok, {:__aliases__, _, list}} -> expand_elixir_modules(list, "") _ -> no() end end defp expand_expr(expr) do case Code.string_to_quoted expr do {:ok, atom} when is_atom(atom) -> expand_erlang_modules(Atom.to_string(atom)) {:ok, {atom, _, nil}} when is_atom(atom) -> expand_import(Atom.to_string(atom)) {:ok, {:__aliases__, _, [root]}} -> expand_elixir_modules([], Atom.to_string(root)) {:ok, {:__aliases__, _, [h|_] = list}} when is_atom(h) -> hint = Atom.to_string(List.last(list)) list = Enum.take(list, length(list) - 1) expand_elixir_modules(list, hint) {:ok, {{:., _, [mod, fun]}, _, []}} when is_atom(fun) -> expand_call(mod, Atom.to_string(fun)) _ -> no() end end defp reduce(expr) do Enum.reverse Enum.reduce ' ([{', expr, fn token, acc -> hd(:string.tokens(acc, [token])) end end defp yes(hint, entries) do {:yes, String.to_char_list(hint), Enum.map(entries, &String.to_char_list/1)} end defp no do {:no, '', []} end ## Formatting defp format_expansion([], _) do no() end defp format_expansion([uniq], hint) do case to_hint(uniq, hint) do "" -> yes("", to_uniq_entries(uniq)) hint -> yes(hint, []) end end defp format_expansion([first|_]=entries, hint) do binary = Enum.map(entries, &(&1.name)) length = byte_size(hint) prefix = :binary.longest_common_prefix(binary) if prefix in [0, length] do yes("", Enum.flat_map(entries, &to_entries/1)) else yes(:binary.part(first.name, prefix, length-prefix), []) end end ## Expand calls # :atom.fun defp expand_call(mod, hint) when is_atom(mod) do expand_require(mod, hint) end # Elixir.fun defp expand_call({:__aliases__, _, list}, hint) do expand_alias(list) |> normalize_module |> expand_require(hint) end defp expand_call(_, _) do no() end defp expand_require(mod, hint) do format_expansion match_module_funs(mod, hint), hint end defp expand_import(hint) do funs = match_module_funs(IEx.Helpers, hint) ++ match_module_funs(Kernel, hint) ++ match_module_funs(Kernel.SpecialForms, hint) format_expansion funs, hint end ## Erlang modules defp expand_erlang_modules(hint \\ "") do format_expansion match_erlang_modules(hint), hint end defp match_erlang_modules(hint) do for mod <- match_modules(hint, true) do %{kind: :module, name: mod, type: :erlang} end end ## Elixir modules defp expand_elixir_modules([], hint) do expand_elixir_modules(Elixir, hint, match_aliases(hint)) end defp expand_elixir_modules(list, hint) do expand_alias(list) |> normalize_module |> expand_elixir_modules(hint, []) end defp expand_elixir_modules(mod, hint, aliases) do aliases |> Kernel.++(match_elixir_modules(mod, hint)) |> Kernel.++(match_module_funs(mod, hint)) |> format_expansion(hint) end defp expand_alias([name | rest] = list) do module = Module.concat(Elixir, name) Enum.find_value env_aliases(), list, fn {alias, mod} -> if alias === module do case Atom.to_string(mod) do "Elixir." <> mod -> Module.concat [mod|rest] _ -> mod end end end end defp env_aliases do Application.get_env(:iex, :autocomplete_server).current_env.aliases end defp match_aliases(hint) do for {alias, _mod} <- env_aliases(), [name] = Module.split(alias), starts_with?(name, hint) do %{kind: :module, type: :alias, name: name} end end defp match_elixir_modules(module, hint) do name = Atom.to_string(module) depth = length(String.split(name, ".")) + 1 base = name <> "." <> hint for mod <- match_modules(base, module === Elixir), parts = String.split(mod, "."), depth <= length(parts) do %{kind: :module, type: :elixir, name: Enum.at(parts, depth-1)} end |> Enum.uniq end ## Helpers defp normalize_module(mod) do if is_list(mod) do Module.concat(mod) else mod end end defp match_modules(hint, root) do get_modules(root) |> :lists.usort() |> Enum.drop_while(& not starts_with?(&1, hint)) |> Enum.take_while(& starts_with?(&1, hint)) end defp get_modules(true) do ["Elixir.Elixir"] ++ get_modules(false) end defp get_modules(false) do modules = Enum.map(:code.all_loaded(), &Atom.to_string(elem(&1, 0))) case :code.get_mode() do :interactive -> modules ++ get_modules_from_applications() _otherwise -> modules end end defp get_modules_from_applications do for [app] <- loaded_applications(), {:ok, modules} = :application.get_key(app, :modules), module <- modules do Atom.to_string(module) end end defp loaded_applications do # If we invoke :application.loaded_applications/0, # it can error if we don't call safe_fixtable before. # Since in both cases we are reaching over the # application controller internals, we choose to match # for performance. :ets.match(:ac_tab, {{:loaded, :"$1"}, :_}) end defp match_module_funs(mod, hint) do case ensure_loaded(mod) do {:module, _} -> falist = get_module_funs(mod) list = Enum.reduce falist, [], fn {f, a}, acc -> case :lists.keyfind(f, 1, acc) do {f, aa} -> :lists.keyreplace(f, 1, acc, {f, [a|aa]}) false -> [{f, [a]}|acc] end end for {fun, arities} <- list, name = Atom.to_string(fun), starts_with?(name, hint) do %{kind: :function, name: name, arities: arities} end |> :lists.sort() _otherwise -> [] end end defp get_module_funs(mod) do if function_exported?(mod, :__info__, 1) do if docs = Code.get_docs(mod, :docs) do for {tuple, _line, _kind, _sign, doc} <- docs, doc != false, do: tuple else mod.__info__(:macros) ++ (mod.__info__(:functions) -- [__info__: 1]) end else mod.module_info(:exports) end end defp ensure_loaded(Elixir), do: {:error, :nofile} defp ensure_loaded(mod), do: Code.ensure_compiled(mod) defp starts_with?(_string, ""), do: true defp starts_with?(string, hint), do: String.starts_with?(string, hint) ## Ad-hoc conversions defp to_entries(%{kind: :module, name: name}) do [name] end defp to_entries(%{kind: :function, name: name, arities: arities}) do for a <- :lists.sort(arities), do: "#{name}/#{a}" end defp to_uniq_entries(%{kind: :module}) do [] end defp to_uniq_entries(%{kind: :function} = fun) do to_entries(fun) end defp to_hint(%{kind: :module, name: name}, hint) do format_hint(name, hint) <> "." end defp to_hint(%{kind: :function, name: name}, hint) do format_hint(name, hint) end defp format_hint(name, hint) do hint_size = byte_size(hint) :binary.part(name, hint_size, byte_size(name) - hint_size) end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/cli.ex000066400000000000000000000101751254730255300211140ustar00rootroot00000000000000# IEx sets the Erlang user to be IEx.CLI via the command line. # While this works most of the time, there are some problems # that may happen depending on how the booting process goes. # Those problems need to be manually tested in case changes are # done to this file. # # 1. In some situations, printing something before the shell # starts becomes very slow. To verify this feature, just # get an existing project and run: # # $ mix clean # $ iex -S mix # # If the printing of data is slower than usual. This particular # bug has arisen; # # 2. In some situations, connecting to a remote node via --remsh # is not possible. This can be tested by starting two iex nodes: # # $ iex --sname foo # $ iex --sname bar --remsh foo@localhost # # 3. When still using --remsh, we need to guarantee the arguments # are processed on the local node and not the remote one. For such, # one can replace the last line above by: # # $ iex --sname bar --remsh foo@localhost -e IO.inspect node # # And verify that the local node name is printed. # # 4. Finally, in some other circumstances, printing messages may become # borked. This can be verified with: # # $ iex -e ":error_logger.info_msg("foo~nbar", [])" # # By the time those instructions have been written, all tests above pass. defmodule IEx.CLI do @moduledoc false @doc """ In order to work properly, IEx needs to be set as the proper `-user` when starting the Erlang VM and we do so by pointing exactly to this function. If possible, Elixir will start a tty (smart terminal) which makes all control commands available in tty available to the developer. In case `tty` is not available (for example, Windows), a dumb terminal version is started instead. """ def start do if tty_works? do :user_drv.start([:"tty_sl -c -e", tty_args]) else :application.set_env(:stdlib, :shell_prompt_func, {__MODULE__, :prompt}) :user.start() local_start() end end def prompt(_n) do [] end # Check if tty works. If it does not, we fall back to the # simple/dumb terminal. This is starting the linked in # driver twice, it would be nice and appropriate if we had # to do it just once. defp tty_works? do try do port = Port.open {:spawn, 'tty_sl -c -e'}, [:eof] Port.close(port) catch _, _ -> false end end defp tty_args do if remote = get_remsh(:init.get_plain_arguments) do if Node.alive? do case :rpc.call remote, :code, :ensure_loaded, [IEx] do {:badrpc, reason} -> abort "Could not contact remote node #{remote}, reason: #{inspect reason}. Aborting..." {:module, IEx} -> {remote, :erlang, :apply, [remote_start_function, []]} _ -> abort "Could not find IEx on remote node #{remote}. Aborting..." end else abort "In order to use --remsh, you need to name the current node using --name or --sname. Aborting..." end else {:erlang, :apply, [local_start_function, []]} end end def local_start do IEx.start(options(), {:elixir, :start_cli, []}) end def remote_start(parent, ref) do send parent, {:begin, ref, self} receive do: ({:done, ^ref} -> :ok) end defp local_start_function do &local_start/0 end defp remote_start_function do ref = make_ref opts = options() parent = spawn_link fn -> receive do {:begin, ^ref, other} -> :elixir.start_cli send other, {:done, ref} end end fn -> IEx.start(opts, {__MODULE__, :remote_start, [parent, ref]}) end end defp options do [dot_iex_path: find_dot_iex(:init.get_plain_arguments)] end defp abort(msg) do function = fn -> IO.puts(:stderr, msg) System.halt(1) end {:erlang, :apply, [function, []]} end defp find_dot_iex(['--dot-iex', h|_]), do: List.to_string(h) defp find_dot_iex([_|t]), do: find_dot_iex(t) defp find_dot_iex([]), do: nil defp get_remsh(['--remsh', h|_]), do: List.to_atom(h) defp get_remsh([_|t]), do: get_remsh(t) defp get_remsh([]), do: nil end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/config.ex000066400000000000000000000112401254730255300216040ustar00rootroot00000000000000defmodule IEx.Config do @moduledoc false @table __MODULE__ @agent __MODULE__ @keys [:colors, :inspect, :history_size, :default_prompt, :alive_prompt] @colors [:eval_interrupt, :eval_result, :eval_error, :eval_info, :stack_app, :stack_info, :ls_directory, :ls_device] def new() do tab = :ets.new(@table, [:named_table, :public]) true = :ets.insert_new(tab, [after_spawn: []]) tab end def delete(__MODULE__) do :ets.delete(__MODULE__) end def configure(options) do Agent.update(@agent, __MODULE__, :handle_configure, [options]) end def handle_configure(tab, options) do options = :lists.ukeysort(1, options) get_config() |> Keyword.merge(options, &merge_option/3) |> put_config() tab end defp get_config() do Application.get_all_env(:iex) |> Keyword.take(@keys) end defp put_config(config) do put = fn({key, value}) when key in @keys -> Application.put_env(:iex, key, value) end Enum.each(config, put) end defp merge_option(:colors, old, new) when is_list(new), do: Keyword.merge(old, new) defp merge_option(:inspect, old, new) when is_list(new), do: Keyword.merge(old, new) defp merge_option(:history_size, _old, new) when is_integer(new), do: new defp merge_option(:default_prompt, _old, new) when is_binary(new), do: new defp merge_option(:alive_prompt, _old, new) when is_binary(new), do: new defp merge_option(k, _old, new) do raise ArgumentError, "invalid configuration or value for pair #{inspect k} - #{inspect new}" end def configuration() do Keyword.merge(default_config(), get_config(), &merge_option/3) end defp default_config() do Enum.map(@keys, &{&1, default_option(&1)}) end defp default_option(:colors), do: [{:enabled, IO.ANSI.enabled?} | default_colors()] defp default_option(:inspect), do: [] defp default_option(:history_size), do: 20 defp default_option(prompt) when prompt in [:default_prompt, :alive_prompt] do "%prefix(%counter)>" end defp default_colors() do Enum.map(@colors, &{&1, default_color(&1)}) ++ default_doc_colors() end defp default_doc_colors() do Keyword.drop(IO.ANSI.Docs.default_options(), [:enabled, :width]) end # Used by default on evaluation cycle defp default_color(:eval_interrupt), do: [:yellow] defp default_color(:eval_result), do: [:yellow] defp default_color(:eval_error), do: [:red] defp default_color(:eval_info), do: [:normal] defp default_color(:stack_app), do: [:red, :bright] defp default_color(:stack_info), do: [:red] # Used by ls defp default_color(:ls_directory), do: [:blue] defp default_color(:ls_device), do: [:green] # Used by ansi docs defp default_color(doc_color) do IO.ANSI.Docs.default_options() |> Keyword.fetch!(doc_color) end def color(color) do colors = Application.get_env(:iex, :colors, []) if colors_enabled?(colors) do case Keyword.fetch(colors, color) do {:ok, value} -> value :error -> default_color(color) end else nil end end defp colors_enabled?(colors \\ Application.get_env(:iex, :colors, [])) do case Keyword.fetch(colors, :enabled) do {:ok, enabled} -> enabled :error -> IO.ANSI.enabled?() end end def ansi_docs() do colors = Application.get_env(:iex, :colors, []) if enabled = colors_enabled?(colors) do [width: width(), enabled: enabled] ++ colors end end def inspect_opts() do inspect_options = Application.get_env(:iex, :inspect, []) ++ [pretty: true] cond do Keyword.has_key?(inspect_options, :width) -> inspect_options colors_enabled? -> [width: width()] ++ inspect_options true -> inspect_options end end def width() do case :io.columns() do {:ok, width} -> min(width, 80) {:error, _} -> 80 end end def after_spawn(fun) do Agent.update(@agent, __MODULE__, :handle_after_spawn, [fun]) end def handle_after_spawn(tab, fun) do :ets.update_element(tab, :after_spawn, {2, [fun | after_spawn()]}) end def after_spawn() do :ets.lookup_element(@table, :after_spawn, 2) end def started?() do Process.whereis(@agent) !== nil end def history_size(), do: get(:history_size) def default_prompt(), do: get(:default_prompt) def alive_prompt(), do: get(:alive_prompt) defp get(key) do case Application.fetch_env(:iex, key) do {:ok, value} -> value :error -> default_option(key) end end def start_link() do Agent.start_link(__MODULE__, :init, [@table], [name: @agent]) end def init(tab) do :public = :ets.info(tab, :protection) tab end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/evaluator.ex000066400000000000000000000140671254730255300223530ustar00rootroot00000000000000defmodule IEx.Evaluator do @moduledoc false @doc """ Eval loop for an IEx session. Its responsibilities include: * loading of .iex files * evaluating code * trapping exceptions in the code being evaluated * keeping expression history """ def start(server, leader) do old_leader = Process.group_leader Process.group_leader(self, leader) try do loop(server, IEx.History.init) after Process.group_leader(self, old_leader) end end defp loop(server, history) do receive do {:eval, ^server, code, state} -> {result, history} = eval(code, state, history) send server, {:evaled, self, result} loop(server, history) {:done, ^server} -> :ok end end @doc """ Locates and loads an .iex.exs file from one of predefined locations. Returns the new state. """ def load_dot_iex(state, path \\ nil) do candidates = if path do [path] else Enum.map [".iex.exs", "~/.iex.exs"], &Path.expand/1 end path = Enum.find candidates, &File.regular?/1 if is_nil(path) do state else eval_dot_iex(state, path) end end defp eval_dot_iex(state, path) do try do code = File.read!(path) env = :elixir.env_for_eval(state.env, file: path, line: 1) # Evaluate the contents in the same environment server_loop will run in {_result, binding, env, _scope} = :elixir.eval(String.to_char_list(code), state.binding, env) %{state | binding: binding, env: :elixir.env_for_eval(env, file: "iex", line: 1)} catch kind, error -> io_result "Error while evaluating: #{path}" print_error(kind, error, System.stacktrace) System.halt(1) end end # Instead of doing just `:elixir.eval`, we first parse the expression to see # if it's well formed. If parsing succeeds, we evaluate the AST as usual. # # If parsing fails, this might be a TokenMissingError which we treat in # a special way (to allow for continuation of an expression on the next # line in IEx). In case of any other error, we let :elixir_translator # to re-raise it. # # Returns updated state. # # The first two clauses provide support for the break-trigger allowing to # break out from a pending incomplete expression. See # https://github.com/elixir-lang/elixir/issues/1089 for discussion. @break_trigger '#iex:break\n' defp eval(code, state, history) do try do do_eval(String.to_char_list(code), state, history) catch kind, error -> print_error(kind, error, System.stacktrace) {%{state | cache: ''}, history} end end defp do_eval(@break_trigger, %IEx.State{cache: ''} = state, history) do {state, history} end defp do_eval(@break_trigger, state, _history) do :elixir_errors.parse_error(state.counter, "iex", "incomplete expression", "") end defp do_eval(latest_input, state, history) do code = state.cache ++ latest_input line = state.counter Process.put(:iex_history, history) handle_eval(Code.string_to_quoted(code, [line: line, file: "iex"]), code, line, state, history) after Process.delete(:iex_history) end defp handle_eval({:ok, forms}, code, line, state, history) do {result, binding, env, scope} = :elixir.eval_forms(forms, state.binding, state.env, state.scope) unless result == IEx.dont_display_result, do: io_inspect(result) state = %{state | env: env, cache: '', scope: scope, binding: binding, counter: state.counter + 1} {state, update_history(history, line, code, result)} end defp handle_eval({:error, {_, _, ""}}, code, _line, state, history) do # Update state.cache so that IEx continues to add new input to # the unfinished expression in `code` {%{state | cache: code}, history} end defp handle_eval({:error, {line, error, token}}, _code, _line, _state, _) do # Encountered malformed expression :elixir_errors.parse_error(line, "iex", error, token) end defp update_history(history, counter, cache, result) do IEx.History.append(history, {counter, cache, result}, IEx.Config.history_size) end defp io_inspect(result) do io_result inspect(result, IEx.inspect_opts) end defp io_result(result) do IO.puts :stdio, IEx.color(:eval_result, result) end defp io_error(result) do IO.puts :stdio, IEx.color(:eval_error, result) end ## Error handling defp print_error(kind, reason, stacktrace) do message = Exception.format_banner(kind, reason, stacktrace) io_error message io_error (stacktrace |> prune_stacktrace |> format_stacktrace) end @elixir_internals [:elixir_exp, :elixir_compiler, :elixir_module, :elixir_exp_clauses, :elixir_translator, :elixir_expand, :elixir_lexical, :elixir_clauses] defp prune_stacktrace(stacktrace) do # The order in which each drop_while is listed is important. # For example, the user my call Code.eval_string/2 in IEx # and if there is an error we should not remove erl_eval # and eval_bits information from the user stacktrace. stacktrace |> Enum.reverse() |> Enum.drop_while(&(elem(&1, 0) == __MODULE__)) |> Enum.drop_while(&(elem(&1, 0) == :elixir)) |> Enum.drop_while(&(elem(&1, 0) in [:erl_eval, :eval_bits])) |> Enum.reverse() |> Enum.reject(&(elem(&1, 0) in @elixir_internals)) end @doc false def format_stacktrace(trace) do entries = for entry <- trace do split_entry(Exception.format_stacktrace_entry(entry)) end width = Enum.reduce entries, 0, fn {app, _}, acc -> max(String.length(app), acc) end " " <> Enum.map_join(entries, "\n ", &format_entry(&1, width)) end defp split_entry(entry) do case entry do "(" <> _ -> case :binary.split(entry, ") ") do [left, right] -> {left <> ") ", right} _ -> {"", entry} end _ -> {"", entry} end end defp format_entry({app, info}, width) do app = String.rjust(app, width) IEx.color(:stack_app, app) <> IEx.color(:stack_info, info) end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/helpers.ex000066400000000000000000000327331254730255300220130ustar00rootroot00000000000000defmodule IEx.Helpers do @moduledoc """ Welcome to Interactive Elixir. You are currently seeing the documentation for the module `IEx.Helpers` which provides many helpers to make Elixir's shell more joyful to work with. This message was triggered by invoking the helper `h()`, usually referred to as `h/0` (since it expects 0 arguments). There are many other helpers available: * `c/2` — compiles a file at the given path * `cd/1` — changes the current directory * `clear/0` — clears the screen * `flush/0` — flushes all messages sent to the shell * `h/0` — prints this help message * `h/1` — prints help for the given module, function or macro * `l/1` — loads the given module's beam code * `ls/0` — lists the contents of the current directory * `ls/1` — lists the contents of the specified directory * `pwd/0` — prints the current working directory * `r/1` — recompiles and reloads the given module's source file * `respawn/0` — respawns the current shell * `s/1` — prints spec information * `t/1` — prints type information * `v/0` — retrieves the last value from the history * `v/1` — retrieves the nth value from the history * `import_file/1` — evaluates the given file in the shell's context Help for functions in this module can be consulted directly from the command line, as an example, try: h(c/2) You can also retrieve the documentation for any module or function. Try these: h(Enum) h(Enum.reverse/1) To discover all available functions for a module, type the module name followed by a dot, then press tab to trigger autocomplete. For example: Enum. To learn more about IEx as a whole, just type `h(IEx)`. """ import IEx, only: [dont_display_result: 0] @doc """ Compiles the given files. It expects a list of files to compile and an optional path to write the compiled code to (defaults to the current directory). When compiling one file, there is no need to wrap it in a list. It returns the name of the compiled modules. If you want to recompile an existing module, check `r/1` instead. ## Examples c ["foo.ex", "bar.ex"], "ebin" #=> [Foo, Bar] c "baz.ex" #=> [Baz] """ def c(files, path \\ ".") when is_binary(path) do files = List.wrap(files) unless Enum.all?(files, &is_binary/1) do raise ArgumentError, "expected a binary or a list of binaries as argument" end {found, not_found} = files |> Enum.map(&Path.expand(&1, path)) |> Enum.partition(&File.exists?/1) unless Enum.empty?(not_found) do raise ArgumentError, "could not find files #{Enum.join(not_found, ", ")}" end {erls, exs} = Enum.partition(found, &String.ends_with?(&1, ".erl")) modules = Enum.map(erls, fn(source) -> {module, binary} = compile_erlang(source) base = source |> Path.basename |> Path.rootname File.write!(Path.join(path, base <> ".beam"), binary) module end) modules ++ Kernel.ParallelCompiler.files_to_path(exs, path) end @doc """ Clears the console screen. This function only works if ANSI escape codes are enabled on the shell, which means this function is by default unavailable on Windows machines. """ def clear do if IO.ANSI.enabled? do IO.write [IO.ANSI.home, IO.ANSI.clear] else IO.puts "Cannot clear the screen because ANSI escape codes are not enabled on this shell" end dont_display_result end @doc """ Prints the documentation for `IEx.Helpers`. """ def h() do IEx.Introspection.h(IEx.Helpers) dont_display_result end @doc """ Prints the documentation for the given module or for the given function/arity pair. ## Examples h(Enum) #=> Prints documentation for Enum It also accepts functions in the format `fun/arity` and `module.fun/arity`, for example: h receive/1 h Enum.all?/2 h Enum.all? """ @h_modules [__MODULE__, Kernel, Kernel.SpecialForms] defmacro h(term) defmacro h({:/, _, [call, arity]} = term) do args = case Macro.decompose_call(call) do {_mod, :__info__, []} when arity == 1 -> [Module, :__info__, 1] {mod, fun, []} -> [mod, fun, arity] {fun, []} -> [@h_modules, fun, arity] _ -> [term] end quote do IEx.Introspection.h(unquote_splicing(args)) end end defmacro h(call) do args = case Macro.decompose_call(call) do {_mod, :__info__, []} -> [Module, :__info__, 1] {mod, fun, []} -> [mod, fun] {fun, []} -> [@h_modules, fun] _ -> [call] end quote do IEx.Introspection.h(unquote_splicing(args)) end end @doc """ Prints the documentation for the given callback function. It also accepts single module argument to list all available behaviour callbacks. ## Examples b(Mix.Task.run/1) b(Mix.Task.run) b(Dict) """ defmacro b(term) defmacro b({:/, _, [{{:., _, [mod, fun]}, _, []}, arity]}) do quote do IEx.Introspection.b(unquote(mod), unquote(fun), unquote(arity)) end end defmacro b({{:., _, [mod, fun]}, _, []}) do quote do IEx.Introspection.b(unquote(mod), unquote(fun)) end end defmacro b(module) do quote do IEx.Introspection.b(unquote(module)) end end @doc """ Prints the types for the given module or for the given function/arity pair. ## Examples t(Enum) t(Enum.t/0) t(Enum.t) """ defmacro t(term) defmacro t({:/, _, [{{:., _, [mod, fun]}, _, []}, arity]}) do quote do IEx.Introspection.t(unquote(mod), unquote(fun), unquote(arity)) end end defmacro t({{:., _, [mod, fun]}, _, []}) do quote do IEx.Introspection.t(unquote(mod), unquote(fun)) end end defmacro t(module) do quote do IEx.Introspection.t(unquote(module)) end end @doc """ Prints the specs for the given module or for the given function/arity pair. ## Examples s(Enum) s(Enum.all?) s(Enum.all?/2) s(is_atom) s(is_atom/1) """ defmacro s(term) defmacro s({:/, _, [call, arity]} = term) do args = case Macro.decompose_call(call) do {mod, fun, []} -> [mod, fun, arity] {fun, []} -> [Kernel, fun, arity] _ -> [term] end quote do IEx.Introspection.s(unquote_splicing(args)) end end defmacro s(call) do args = case Macro.decompose_call(call) do {mod, fun, []} -> [mod, fun] {fun, []} -> [Kernel, fun] _ -> [call] end quote do IEx.Introspection.s(unquote_splicing(args)) end end @doc """ Retrieves the nth expression's value from the history. Use negative values to lookup expression values relative to the current one. For instance, v(-1) returns the result of the last evaluated expression. """ def v(n \\ -1) do IEx.History.nth(history, n) |> elem(2) end @doc """ Recompiles and reloads the given `module`. Please note that all the modules defined in the same file as `module` are recompiled and reloaded. ## In-memory reloading When we reload the module in IEx, we recompile the module source code, updating its contents in memory. The original `.beam` file in disk, probably the one where the first definition of the module came from, does not change at all. Since typespecs and docs are loaded from the .beam file (they are not loaded in memory with the module because there is no need for them to be in memory), they are not reloaded when you reload the module. """ def r(module) when is_atom(module) do {:reloaded, module, do_r(module)} end defp do_r(module) do unless Code.ensure_loaded?(module) do raise ArgumentError, "could not load nor find module: #{inspect module}" end source = source(module) cond do source == nil -> raise ArgumentError, "could not find source for module: #{inspect module}" not File.exists?(source) -> raise ArgumentError, "could not find source (#{source}) for module: #{inspect module}" String.ends_with?(source, ".erl") -> [compile_erlang(source) |> elem(0)] true -> Enum.map(Code.load_file(source), fn {name, _} -> name end) end end @doc """ Loads the given module's beam code (and ensures any previous old version was properly purged before). This function is useful when you know the bytecode for module has been updated in the filesystem and you want to tell the VM to load it. """ def l(module) when is_atom(module) do :code.purge(module) :code.load_file(module) end @doc """ Flushes all messages sent to the shell and prints them out. """ def flush do do_flush(IEx.inspect_opts) end defp do_flush(inspect_opts) do receive do msg -> IO.inspect(msg, inspect_opts) do_flush(inspect_opts) after 0 -> :ok end end defp source(module) do source = module.module_info(:compile)[:source] case source do nil -> nil source -> List.to_string(source) end end @doc """ Prints the current working directory. """ def pwd do IO.puts IEx.color(:eval_info, System.cwd!) end @doc """ Changes the current working directory to the given path. """ def cd(directory) when is_binary(directory) do case File.cd(expand_home(directory)) do :ok -> pwd {:error, :enoent} -> IO.puts IEx.color(:eval_error, "No directory #{directory}") end end @doc """ Produces a simple list of a directory's contents. If `path` points to a file, prints its full path. """ def ls(path \\ ".") when is_binary(path) do path = expand_home(path) case File.ls(path) do {:ok, items} -> sorted_items = Enum.sort(items) ls_print(path, sorted_items) {:error, :enoent} -> IO.puts IEx.color(:eval_error, "No such file or directory #{path}") {:error, :enotdir} -> IO.puts IEx.color(:eval_info, Path.absname(path)) end end defp expand_home(<>) do System.user_home! <> rest end defp expand_home(other), do: other defp ls_print(_, []) do :ok end defp ls_print(path, list) do # print items in multiple columns (2 columns in the worst case) lengths = Enum.map(list, &String.length(&1)) maxlen = maxlength(lengths) width = min(maxlen, 30) + 5 ls_print(path, list, width) end defp ls_print(path, list, width) do Enum.reduce(list, 0, fn(item, len) -> if len >= 80 do IO.puts "" len = 0 end IO.write format_item(Path.join(path, item), String.ljust(item, width)) len+width end) IO.puts "" end defp maxlength(list) do Enum.reduce(list, 0, &max(&1, &2)) end defp format_item(path, representation) do case File.stat(path) do {:ok, %File.Stat{type: :device}} -> IEx.color(:ls_device, representation) {:ok, %File.Stat{type: :directory}} -> IEx.color(:ls_directory, representation) _ -> representation end end @doc """ Respawns the current shell by starting a new shell process. Returns `true` if it worked. """ def respawn do if whereis = IEx.Server.whereis do send whereis, {:respawn, self} dont_display_result end end @doc """ Evaluates the contents of the file at `path` as if it were directly typed into the shell. `path` has to be a literal string. `path` is automatically expanded via `Path.expand/1`. ## Non-existent files By default, `import_file/1` fails when the given file does not exist. However, since this macro is expanded at compile-time, it's not possible to conditionally import a file since the macro is always expanded: # This raises a File.Error if ~/.iex.exs doesn't exist. if ("~/.iex.exs" |> Path.expand |> File.exists?) do import_file "~/.iex.exs" end This is why an `:optional` option can be passed to `import_file/1`. The default value of this option is `false`, meaning that an exception will be raised if the given file is missing. If `:optional` is set to `true`, missing files will be ignored and `import_file/1` will just compile to `nil`. ## Examples # ~/file.exs value = 13 # in the shell iex(1)> import_file "~/file.exs" 13 iex(2)> value 13 iex(3)> import_file "nonexisting.file.ex", optional: true nil """ defmacro import_file(path, opts \\ []) defmacro import_file(path, opts) when is_binary(path) do optional? = Keyword.get(opts, :optional, false) path = Path.expand(path) if not optional? or File.exists?(path) do path |> File.read! |> Code.string_to_quoted!(file: path) end end defmacro import_file(_path, _opts) do raise ArgumentError, "import_file/1 expects a literal binary as its argument" end # Compiles and loads an erlang source file, returns {module, binary} defp compile_erlang(source) do source = Path.relative_to_cwd(source) |> String.to_char_list case :compile.file(source, [:binary, :report]) do {:ok, module, binary} -> :code.purge(module) {:module, module} = :code.load_binary(module, source, binary) {module, binary} _ -> raise CompileError end end defp history, do: Process.get(:iex_history) end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/history.ex000066400000000000000000000067071254730255300220540ustar00rootroot00000000000000defmodule IEx.History.State do @moduledoc false defstruct queue: :queue.new, size: 0, start: 1 def append(%{queue: q, size: size} = state, item) do %{state | queue: :queue.in(item, q), size: size + 1} end def to_list(%{queue: q}), do: :queue.to_list(q) # Traverses the queue front-to-back if the index is positive. def nth(%{queue: q, size: size, start: start}, n) when n - start >= 0 and n - start < size, do: get_nth(q, n - start) # Traverses the queue back-to-front if the index is negative. def nth(%{queue: q, size: size, start: start}, n) when n < 0 and size + n >= start - 1, do: get_nth(:queue.reverse(q), abs(n) - 1) def nth(_, _), do: nil defp get_nth(q, 0), do: :queue.head(q) defp get_nth(q, n) when n > 0, do: get_nth(:queue.tail(q), n - 1) # Traverses the queue front-to-back, dropping items as we go # until its size is within the specified limit. # # The `start` value contains the index of the expression at the head # of the queue. def prune(%{start: start} = state, limit), do: prune(state, start, limit, false) defp prune(state, _, limit, _) when limit < 0, do: {false, state} defp prune(%{size: size} = state, counter, limit, collect?) when size - counter < limit, do: {collect?, %{state | start: counter}} defp prune(%{queue: q} = state, counter, limit, collect?) do {{:value, entry}, q} = :queue.out(q) unless collect? do collect? = has_binary(entry) end prune(%{state | queue: q}, counter + 1, limit, collect?) end # Checks val and each of its elements (if it is a list or a tuple) # recursively to see if it has any large binaries (outside of the heap). defp has_binary(val) do try do has_bin(val) catch :throw, :found -> true end end defp has_bin(val) when is_tuple(val), do: has_bin(val, tuple_size(val) - 1) defp has_bin([head | tail]) do has_bin(head) has_bin(tail) end defp has_bin(val) when byte_size(val) > 64, do: throw(:found) defp has_bin(_), do: false defp has_bin(_, -1), do: false defp has_bin(tuple, index) do has_bin(elem(tuple, index)) has_bin(tuple, index - 1) end end defmodule IEx.History do @moduledoc false alias IEx.History.State @doc """ Initializes IEx history state. """ def init(), do: %State{} @doc """ Appends one entry to the history. """ def append(%State{} = state, entry, limit) do {collect?, state} = State.append(state, entry) |> State.prune(limit) if collect?, do: collect_garbage() state end @doc """ Enumerates over all items in the history starting from the oldest one and applies `fun` to each one in turn. """ def each(%State{} = state, fun) do State.to_list(state) |> Enum.each(fun) end @doc """ Gets the nth item from the history. If `n` < 0, the count starts from the most recent item and goes back in time. """ def nth(%State{} = state, n) do case State.nth(state, n) do nil -> raise "v(#{n}) is out of bounds" entry -> entry end end # Based on https://github.com/erlang/otp/blob/7dcccee4371477e983f026db9e243cb66900b1ef/lib/stdlib/src/shell.erl#L1401 defp collect_garbage() do collect_proc_garbage Process.whereis(:user) collect_proc_garbage Process.group_leader() :erlang.garbage_collect() end defp collect_proc_garbage(process) do try do :erlang.garbage_collect(process) catch _, _ -> nil end end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/introspection.ex000066400000000000000000000266561254730255300232600ustar00rootroot00000000000000# Convenience helpers for showing docs, specs and types # from modules. Invoked directly from IEx.Helpers. defmodule IEx.Introspection do @moduledoc false import IEx, only: [dont_display_result: 0] alias Kernel.Typespec @doc """ Prints the documentation for the given module. """ def h(module) when is_atom(module) do case Code.ensure_loaded(module) do {:module, _} -> if function_exported?(module, :__info__, 1) do case Code.get_docs(module, :moduledoc) do {_, binary} when is_binary(binary) -> print_doc(inspect(module), binary) {_, _} -> nodocs(inspect module) _ -> puts_error("#{inspect module} was not compiled with docs") end else puts_error("#{inspect module} is an Erlang module and, as such, it does not have Elixir-style docs") end {:error, reason} -> puts_error("Could not load module #{inspect module}, got: #{reason}") end dont_display_result end def h(_) do puts_error("Invalid arguments for h helper") dont_display_result end @doc """ Prints the documentation for the given function with any arity in the list of modules. """ def h(modules, function) when is_list(modules) and is_atom(function) do result = Enum.find_value modules, false, fn module -> h_mod_fun(module, function) == :ok end unless result, do: nodocs(function) dont_display_result end def h(module, function) when is_atom(module) and is_atom(function) do case h_mod_fun(module, function) do :ok -> :ok :no_docs -> puts_error("#{inspect module} was not compiled with docs") :not_found -> nodocs("#{inspect module}.#{function}") end dont_display_result end defp h_mod_fun(mod, fun) when is_atom(mod) do if docs = Code.get_docs(mod, :docs) do result = for {{f, arity}, _line, _type, _args, doc} <- docs, fun == f, doc != false do h(mod, fun, arity) end if result != [], do: :ok, else: :not_found else :no_docs end end @doc """ Prints the documentation for the given function and arity in the list of modules. """ def h(modules, function, arity) when is_list(modules) and is_atom(function) and is_integer(arity) do result = Enum.find_value modules, false, fn module -> h_mod_fun_arity(module, function, arity) == :ok end unless result, do: nodocs("#{function}/#{arity}") dont_display_result end def h(module, function, arity) when is_atom(module) and is_atom(function) and is_integer(arity) do case h_mod_fun_arity(module, function, arity) do :ok -> :ok :no_docs -> puts_error("#{inspect module} was not compiled with docs") :not_found -> nodocs("#{inspect module}.#{function}/#{arity}") end dont_display_result end defp h_mod_fun_arity(mod, fun, arity) when is_atom(mod) do if docs = Code.get_docs(mod, :docs) do doc = find_doc(docs, fun, arity, 4) || find_default_doc(docs, fun, arity) if doc do print_doc(doc) :ok else :not_found end else :no_docs end end defp find_doc(docs, function, arity, pos) do if doc = List.keyfind(docs, {function, arity}, 0) do case elem(doc, pos) do false -> nil _ -> doc end end end defp find_default_doc(docs, function, min) do Enum.find docs, fn(doc) -> case elem(doc, 0) do {^function, max} when max > min -> defaults = Enum.count elem(doc, 3), &match?({:\\, _, _}, &1) min + defaults >= max _ -> false end end end defp print_doc({{fun, _}, _line, kind, args, doc}) do args = Enum.map_join(args, ", ", &format_doc_arg(&1)) print_doc("#{kind} #{fun}(#{args})", doc) end defp print_doc(heading, doc) do doc = doc || "" if opts = IEx.Config.ansi_docs do IO.ANSI.Docs.print_heading(heading, opts) IO.ANSI.Docs.print(doc, opts) else IO.puts "* #{heading}\n" IO.puts doc end end defp format_doc_arg({:\\, _, [left, right]}) do format_doc_arg(left) <> " \\\\ " <> Macro.to_string(right) end defp format_doc_arg({var, _, _}) do Atom.to_string(var) end @doc """ Prints the list of behaviour callbacks for the given module. """ def b(mod) when is_atom(mod) do printer = &puts_callback_info/2 case print_behaviour_docs(mod, &match?(_, &1), printer) do :ok -> :ok :no_beam -> nobeam(mod) :no_docs -> puts_error("#{inspect mod} was not compiled with docs") :not_found -> puts_error("No callbacks for #{inspect mod} were found") end dont_display_result end defp puts_callback_info("defc" <> _rest = heading, _doc), do: puts_info(" " <> heading) defp puts_callback_info(heading, _doc), do: puts_info(heading) @doc """ Prints documentation for the given callback function with any arity. """ def b(mod, fun) when is_atom(mod) and is_atom(fun) do filter = &match?({^fun, _}, elem(&1, 0)) case print_behaviour_docs(mod, filter, &print_doc/2) do :ok -> :ok :no_beam -> nobeam(mod) :no_docs -> puts_error("#{inspect mod} was not compiled with docs") :not_found -> nodocs("#{inspect mod}.#{fun}") end dont_display_result end @doc """ Prints documentation for the given callback function and arity. """ def b(mod, fun, arity) when is_atom(mod) and is_atom(fun) and is_integer(arity) do filter = &match?({^fun, ^arity}, elem(&1, 0)) case print_behaviour_docs(mod, filter, &print_doc/2) do :ok -> :ok :no_beam -> nobeam(mod) :no_docs -> puts_error("#{inspect mod} was not compiled with docs") :not_found -> nodocs("#{inspect mod}.#{fun}/#{arity}") end dont_display_result end defp print_behaviour_docs(mod, filter, printer) do case get_behaviour_docs(mod) do {callbacks, docs} -> printed = Enum.filter_map docs, filter, fn {{fun, arity}, _, :defmacro, doc} -> print_callback_doc(fun, :defmacro, doc, {:"MACRO-#{fun}", arity + 1}, callbacks, printer) {{fun, arity}, _, kind, doc} -> print_callback_doc(fun, kind, doc, {fun, arity}, callbacks, printer) end if Enum.any?(printed), do: :ok, else: :not_found other -> other end end defp get_behaviour_docs(mod) do callbacks = Typespec.beam_callbacks(mod) docs = Code.get_docs(mod, :behaviour_docs) cond do is_nil(callbacks) -> :no_beam is_nil(docs) -> :no_docs true -> {callbacks, docs} end end defp print_callback_doc(name, kind, doc, key, callbacks, printer) do {_, [spec | _]} = List.keyfind(callbacks, key, 0) definition = Typespec.spec_to_ast(name, spec) |> Macro.prewalk(&drop_macro_env/1) |> Macro.to_string printer.("#{kind}callback #{definition}", doc) end defp drop_macro_env({name, meta, [{:::, _, [{:env, _, _}, _ | _]} | args]}), do: {name, meta, args} defp drop_macro_env(other), do: other @doc """ Prints the types for the given module. """ def t(module) when is_atom(module) do _ = case Typespec.beam_types(module) do nil -> nobeam(module) [] -> notypes(inspect module) types -> for type <- types, do: print_type(type) end dont_display_result end @doc """ Prints the given type in module with any arity. """ def t(module, type) when is_atom(module) and is_atom(type) do case Typespec.beam_types(module) do nil -> nobeam(module) types -> printed = for {_, {t, _, _args}} = typespec <- types, t == type do print_type(typespec) typespec end if printed == [] do notypes("#{inspect module}.#{type}") end end dont_display_result end @doc """ Prints the type in module with given arity. """ def t(module, type, arity) when is_atom(module) and is_atom(type) and is_integer(arity) do case Typespec.beam_types(module) do nil -> nobeam(module) types -> printed = for {_, {t, _, args}} = typespec <- types, t == type, length(args) == arity do print_type(typespec) typespec end if printed == [] do notypes("#{inspect module}.#{type}") end end dont_display_result end @doc """ Prints the specs for given module. """ def s(module) when is_atom(module) do case beam_specs(module) do nil -> nobeam(module) [] -> nospecs(inspect module) specs -> printed = for {_kind, {{f, _arity}, _spec}} = spec <- specs, f != :"__info__" do print_spec(spec) end if printed == [] do nospecs(inspect module) end end dont_display_result end @doc """ Prints the specs for given module and function. """ def s(module, function) when is_atom(module) and is_atom(function) do case beam_specs(module) do nil -> nobeam(module) specs -> printed = for {_kind, {{f, _arity}, _spec}} = spec <- specs, f == function do print_spec(spec) spec end if printed == [] do nospecs("#{inspect module}.#{function}") end end dont_display_result end @doc """ Prints the spec in given module, with arity. """ def s(module, function, arity) when is_atom(module) and is_atom(function) and is_integer(arity) do case beam_specs(module) do nil -> nobeam(module) specs -> printed = for {_kind, {{f, a}, _spec}} = spec <- specs, f == function and a == arity do print_spec(spec) spec end if printed == [] do nospecs("#{inspect module}.#{function}") end end dont_display_result end defp beam_specs(module) do specs = beam_specs_tag(Typespec.beam_specs(module), :spec) callbacks = beam_specs_tag(Typespec.beam_callbacks(module), :callback) specs && callbacks && Enum.concat(specs, callbacks) end defp beam_specs_tag(nil, _), do: nil defp beam_specs_tag(specs, tag) do Enum.map(specs, &{tag, &1}) end defp print_type({:opaque, type}) do {:::, _, [ast, _]} = Typespec.type_to_ast(type) puts_info("@opaque #{Macro.to_string(ast)}") true end defp print_type({kind, type}) do ast = Typespec.type_to_ast(type) puts_info("@#{kind} #{Macro.to_string(ast)}") true end defp print_spec({kind, {{name, _arity}, specs}}) do Enum.each specs, fn(spec) -> binary = Macro.to_string Typespec.spec_to_ast(name, spec) puts_info("@#{kind} #{binary}") end true end defp nobeam(module) do case Code.ensure_loaded(module) do {:module, _} -> puts_error("Beam code not available for #{inspect module} or debug info is missing, cannot load typespecs") {:error, reason} -> puts_error("Could not load module #{inspect module}, got: #{reason}") end end defp nospecs(for), do: no(for, "specification") defp notypes(for), do: no(for, "type information") defp nodocs(for), do: no(for, "documentation") defp no(for, type) do puts_error("No #{type} for #{for} was found") end defp puts_info(string) do IO.puts IEx.color(:eval_info, string) end defp puts_error(string) do IO.puts IEx.color(:eval_error, string) end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/remsh.ex000066400000000000000000000005361254730255300214630ustar00rootroot00000000000000defmodule IEx.Remsh do @moduledoc false @doc """ Provides one helper function that is injected into connecting remote nodes to properly handle autocompletion. """ def expand(node) do fn e -> case :rpc.call node, IEx.Autocomplete, :expand, [e] do {:badrpc, _} -> {:no, '', []} r -> r end end end end elixir-lang-1.1.0~0.20150708/lib/iex/lib/iex/server.ex000066400000000000000000000216461254730255300216600ustar00rootroot00000000000000defmodule IEx.State do @moduledoc false defstruct binding: nil, cache: '', counter: 1, prefix: "iex", scope: nil, env: nil @type t :: %__MODULE__{} end defmodule IEx.Server do @moduledoc false @doc """ Finds the IEx server, on this or another node. """ @spec whereis :: pid | nil def whereis() do Enum.find_value([node()|Node.list], fn node -> server = :rpc.call(node, IEx.Server, :local, []) if is_pid(server), do: server end) end @doc """ Returns the pid of the IEx server on the local node if exists. """ @spec local :: pid | nil def local() do # Locate top group leader, always registered as user # can be implemented by group (normally) or user # (if oldshell or noshell) if user = Process.whereis(:user) do case :group.interfaces(user) do [] -> # Old or no shell case :user.interfaces(user) do [] -> nil [shell: shell] -> shell end [user_drv: user_drv] -> # Get current group from user_drv case :user_drv.interfaces(user_drv) do [] -> nil [current_group: group] -> :group.interfaces(group)[:shell] end end end end @doc """ Returns the current session environment if a session exists. """ @spec current_env :: Macro.Env.t def current_env() do case IEx.Server.whereis() do nil -> %Macro.Env{} server -> send(server, {:peek_env, self()}) receive do {:peek, %Macro.Env{} = env} -> env after 5000 -> %Macro.Env{} end end end @doc """ Requests to take over the given shell from the current process. """ @spec take_over(binary, Keyword.t, pos_integer) :: :ok | {:error, :no_iex} | {:error, :refused} def take_over(identifier, opts, timeout \\ 1000, server \\ whereis()) do cond do is_nil(server) -> {:error, :no_iex} true -> ref = make_ref() send server, {:take?, self, ref} receive do ^ref -> opts = [evaluator: self] ++ opts send server, {:take, self, identifier, ref, opts} receive do {^ref, nil} -> {:error, :refused} {^ref, leader} -> IEx.Evaluator.start(server, leader) end after timeout -> {:error, :no_iex} end end end @doc """ Starts IEx by executing a given callback and spawning the server only after the callback is done. The server responsibilities include: * reading input * sending messages to the evaluator * handling takeover process of the evaluator If there is any takeover during the callback execution we spawn a new server for it without waiting for its conclusion. """ @spec start(list, {module, atom, [any]}) :: :ok def start(opts, {m, f, a}) do {pid, ref} = spawn_monitor(m, f, a) start_loop(opts, pid, ref) end defp start_loop(opts, pid, ref) do receive do {:take?, other, ref} -> send(other, ref) start_loop(opts, pid, ref) {:take, other, identifier, ref, opts} -> if allow_take?(identifier) do send(other, {ref, Process.group_leader}) run(opts) else send(other, {ref, nil}) start_loop(opts, pid, ref) end {:DOWN, ^ref, :process, ^pid, :normal} -> run(opts) {:DOWN, ^ref, :process, ^pid, _reason} -> :ok end end # Run loop: this is where the work is really # done after the start loop. defp run(opts) when is_list(opts) do IO.puts "Interactive Elixir (#{System.version}) - press Ctrl+C to exit (type h() ENTER for help)" self_pid = self self_leader = Process.group_leader evaluator = opts[:evaluator] || spawn(fn -> IEx.Evaluator.start(self_pid, self_leader) end) Process.put(:evaluator, evaluator) loop(run_state(opts), evaluator, Process.monitor(evaluator)) end defp reset_loop(opts, evaluator, evaluator_ref) do IO.puts("") # We only kill the evaluator if the new evaluator # is not the same as the current one. Otherwise # we end up killing the process that is taking over. exit_loop(evaluator, evaluator_ref, opts[:evaluator] != evaluator) run(opts) end defp exit_loop(evaluator, evaluator_ref, done? \\ true) do Process.delete(:evaluator) Process.demonitor(evaluator_ref, [:flush]) if done? do send(evaluator, {:done, self}) end :ok end defp loop(state, evaluator, evaluator_ref) do self_pid = self() counter = state.counter prefix = if state.cache != [], do: "...", else: state.prefix input = spawn(fn -> io_get(self_pid, prefix, counter) end) wait_input(state, evaluator, evaluator_ref, input) end defp wait_input(state, evaluator, evaluator_ref, input) do receive do {:input, ^input, code} when is_binary(code) -> send evaluator, {:eval, self, code, state} wait_eval(evaluator, evaluator_ref) {:input, ^input, {:error, :interrupted}} -> io_error "** (EXIT) interrupted" loop(%{state | cache: ''}, evaluator, evaluator_ref) {:input, ^input, :eof} -> exit_loop(evaluator, evaluator_ref) {:input, ^input, {:error, :terminated}} -> exit_loop(evaluator, evaluator_ref) {:peek_env, receiver} -> send receiver, {:peek, state.env} wait_input(state, evaluator, evaluator_ref, input) msg -> handle_take_over(msg, evaluator, evaluator_ref, input, fn -> wait_input(state, evaluator, evaluator_ref, input) end) end end defp wait_eval(evaluator, evaluator_ref) do receive do {:evaled, ^evaluator, state} -> loop(state, evaluator, evaluator_ref) msg -> handle_take_over(msg, evaluator, evaluator_ref, nil, fn -> wait_eval(evaluator, evaluator_ref) end) end end # Take process. # # The take? message is received out of band, so we can # go back to wait for the same input. The take message # needs to take hold of the IO, so it kills the input, # re-runs the server OR goes back to the main loop. # # A take process may also happen if the evaluator dies, # then a new evaluator is created to tackle replace the dead # one. defp handle_take_over({:take?, other, ref}, _evaluator, _evaluator_ref, _input, callback) do send(other, ref) callback.() end defp handle_take_over({:take, other, identifier, ref, opts}, evaluator, evaluator_ref, input, callback) do kill_input(input) if allow_take?(identifier) do send other, {ref, Process.group_leader} reset_loop(opts, evaluator, evaluator_ref) else send other, {ref, nil} callback.() end end defp handle_take_over({:respawn, evaluator}, evaluator, evaluator_ref, input, _callback) do kill_input(input) reset_loop([], evaluator, evaluator_ref) end defp handle_take_over({:DOWN, evaluator_ref, :process, evaluator, reason}, evaluator, evaluator_ref, input, _callback) do try do io_error Exception.format_banner({:EXIT, evaluator}, reason) catch type, detail -> io_error "** (IEx.Error) #{type} when printing EXIT message: #{inspect detail}" end kill_input(input) reset_loop([], evaluator, evaluator_ref) end defp handle_take_over(_, _evaluator, _evaluator_ref, _input, callback) do callback.() end defp kill_input(nil), do: :ok defp kill_input(input), do: Process.exit(input, :kill) defp allow_take?(identifier) do message = IEx.color(:eval_interrupt, "#{identifier}. Allow? [Yn] ") IO.gets(:stdio, message) =~ ~r/^(Y(es)?)?$/i end ## State defp run_state(opts) do env = if env = opts[:env] do :elixir.env_for_eval(env, []) else :elixir.env_for_eval(file: "iex") end {_, _, env, scope} = :elixir.eval('import IEx.Helpers', [], env) binding = Keyword.get(opts, :binding, []) prefix = Keyword.get(opts, :prefix, "iex") state = %IEx.State{binding: binding, scope: scope, prefix: prefix, env: env} case opts[:dot_iex_path] do "" -> state path -> IEx.Evaluator.load_dot_iex(state, path) end end ## IO defp io_get(pid, prefix, counter) do prompt = prompt(prefix, counter) send pid, {:input, self, IO.gets(:stdio, prompt)} end defp prompt(prefix, counter) do {mode, prefix} = if Node.alive? do {:alive_prompt, prefix || remote_prefix} else {:default_prompt, prefix || "iex"} end prompt = apply(IEx.Config, mode, []) |> String.replace("%counter", to_string(counter)) |> String.replace("%prefix", to_string(prefix)) |> String.replace("%node", to_string(node)) prompt <> " " end defp io_error(result) do IO.puts :stdio, IEx.color(:eval_error, result) end defp remote_prefix do if node == node(Process.group_leader), do: "iex", else: "rem" end end elixir-lang-1.1.0~0.20150708/lib/iex/mix.exs000066400000000000000000000007101254730255300177640ustar00rootroot00000000000000defmodule IEx.Mixfile do use Mix.Project def project do [app: :iex, version: System.version, build_per_environment: false] end def application do [registered: [IEx.Supervisor, IEx.Config], mod: {IEx.App, []}, env: [ autocomplete_server: IEx.Server, colors: [], inspect: [], history_size: 20, default_prompt: "%prefix(%counter)>", alive_prompt: "%prefix(%node)%counter>"]] end end elixir-lang-1.1.0~0.20150708/lib/iex/test/000077500000000000000000000000001254730255300174275ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/000077500000000000000000000000001254730255300202145ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/autocomplete_test.exs000066400000000000000000000074011254730255300244770ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IEx.AutocompleteTest do use ExUnit.Case, async: true def expand(expr) do IEx.Autocomplete.expand(Enum.reverse expr) end test :erlang_module_completion do assert expand(':zl') == {:yes, 'ib.', []} end test :erlang_module_no_completion do assert expand(':unknown') == {:no, '', []} end test :erlang_module_multiple_values_completion do {:yes, '', list} = expand(':user') assert 'user' in list assert 'user_drv' in list end test :erlang_root_completion do {:yes, '', list} = expand(':') assert is_list(list) assert 'lists' in list end test :elixir_proxy do {:yes, '', list} = expand('E') assert 'Elixir' in list end test :elixir_completion do assert expand('En') == {:yes, 'um', []} assert expand('Enumera') == {:yes, 'ble.', []} end test :elixir_completion_with_self do assert expand('Enumerable') == {:yes, '.', []} end test :elixir_completion_on_modules_from_load_path do assert expand('Str') == {:yes, [], ['Stream', 'String', 'StringIO']} assert expand('Ma') == {:yes, '', ['Macro', 'Map', 'MapSet', 'MatchError']} assert expand('Dic') == {:yes, 't.', []} assert expand('Ex') == {:yes, [], ['ExUnit', 'Exception']} end test :elixir_no_completion do assert expand('.') == {:no, '', []} assert expand('Xyz') == {:no, '', []} assert expand('x.Foo') == {:no, '', []} end test :elixir_root_submodule_completion do assert expand('Elixir.Acce') == {:yes, 'ss.', []} end test :elixir_submodule_completion do assert expand('String.Cha') == {:yes, 'rs.', []} end test :elixir_submodule_no_completion do assert expand('IEx.Xyz') == {:no, '', []} end test :function_completion do assert expand('System.ve') == {:yes, 'rsion', []} assert expand(':ets.fun2') == {:yes, 'ms', []} end test :function_completion_with_arity do assert expand('String.printable?') == {:yes, '', ['printable?/1']} assert expand('String.printable?/') == {:yes, '', ['printable?/1']} end test :macro_completion do {:yes, '', list} = expand('Kernel.is_') assert is_list(list) end test :imports_completion do {:yes, '', list} = expand('') assert is_list(list) assert 'h/1' in list assert 'unquote/1' in list assert 'pwd/0' in list end test :kernel_import_completion do assert expand('defstru') == {:yes, 'ct', []} assert expand('put_') == {:yes, '', ['put_elem/3', 'put_in/2', 'put_in/3']} end test :kernel_special_form_completion do assert expand('unquote_spl') == {:yes, 'icing', []} end test :completion_inside_expression do assert expand('1 En') == {:yes, 'um', []} assert expand('Test(En') == {:yes, 'um', []} assert expand('Test :zl') == {:yes, 'ib.', []} assert expand('[:zl') == {:yes, 'ib.', []} assert expand('{:zl') == {:yes, 'ib.', []} end defmodule SublevelTest.LevelA.LevelB do end test :elixir_completion_sublevel do assert expand('IEx.AutocompleteTest.SublevelTest.') == {:yes, 'LevelA.', []} end defmodule MyServer do def current_env do %Macro.Env{aliases: [{MyList, List}, {EList, :lists}]} end end test :complete_aliases_of_elixir_modules do Application.put_env(:iex, :autocomplete_server, MyServer) assert expand('MyL') == {:yes, 'ist.', []} assert expand('MyList') == {:yes, '.', []} assert expand('MyList.to_integer') == {:yes, [], ['to_integer/1', 'to_integer/2']} end test :complete_aliases_of_erlang_modules do Application.put_env(:iex, :autocomplete_server, MyServer) assert expand('EL') == {:yes, 'ist.', []} assert expand('EList') == {:yes, '.', []} assert expand('EList.map') == {:yes, [], ['map/2', 'mapfoldl/3', 'mapfoldr/3']} end end elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/evaluator_test.exs000066400000000000000000000013041254730255300237740ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IEx.EvaluatorTest do use ExUnit.Case, async: true alias IEx.Evaluator, as: E test "format_stacktrace returns formatted result in columns" do frames = [ {List, :one, 1, [file: "loc", line: 1]}, {String, :second, 2, [file: "loc2", line: 102]}, {IEx, :three, 3, [file: "longer", line: 1234]}, {List, :four, 4, [file: "loc", line: 1]}, ] expected = """ (elixir) loc:1: List.one/1 (elixir) loc2:102: String.second/2 (iex) longer:1234: IEx.three/3 (elixir) loc:1: List.four/4 """ assert E.format_stacktrace(frames) <> "\n" == expected end end elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/helpers_test.exs000066400000000000000000000271751254730255300234520ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IEx.HelpersTest do use IEx.Case import IEx.Helpers test "clear helper" do Application.put_env(:elixir, :ansi_enabled, true) assert capture_iex("clear") == "\e[H\e[2J" Application.put_env(:elixir, :ansi_enabled, false) assert capture_iex("clear") =~ "Cannot clear the screen because ANSI escape codes are not enabled on this shell" after Application.delete_env(:elixir, :ansi_enabled) end test "h helper" do assert "* IEx.Helpers\n\nWelcome to Interactive Elixir" <> _ = capture_iex("h") end test "h helper module" do assert "* IEx.Helpers\n\nWelcome to Interactive Elixir" <> _ = capture_io(fn -> h IEx.Helpers end) assert capture_io(fn -> h :whatever end) == "Could not load module :whatever, got: nofile\n" assert capture_io(fn -> h :lists end) == ":lists is an Erlang module and, as such, it does not have Elixir-style docs\n" end test "h helper function" do pwd_h = "* def pwd()\n\nPrints the current working directory.\n\n" c_h = "* def c(files, path \\\\ \".\")\n\nCompiles the given files." assert capture_io(fn -> h IEx.Helpers.pwd/0 end) =~ pwd_h assert capture_io(fn -> h IEx.Helpers.c/2 end) =~ c_h assert capture_io(fn -> h IEx.Helpers.c/1 end) =~ c_h assert capture_io(fn -> h pwd end) =~ pwd_h end test "h helper __info__" do h_output_module = capture_io(fn -> h Module.__info__ end) assert capture_io(fn -> h Module.UnlikelyTo.Exist.__info__ end) == h_output_module assert capture_io(fn -> h Module.UnlikelyTo.Exist.__info__/1 end) == h_output_module assert capture_io(fn -> h __info__ end) == "No documentation for __info__ was found\n" end test "b helper module" do assert capture_io(fn -> b Mix end) == "No callbacks for Mix were found\n" assert capture_io(fn -> b NoMix end) == "Could not load module NoMix, got: nofile\n" assert capture_io(fn -> b Mix.SCM end) =~ """ defcallback accepts_options(app :: atom(), opts()) :: opts() | nil defcallback checked_out?(opts()) :: boolean() """ end test "b helper function" do assert capture_io(fn -> b Mix.Task.stop end) == "No documentation for Mix.Task.stop was found\n" assert capture_io(fn -> b Mix.Task.run end) =~ "* defcallback run([binary()]) :: any()\n\nA task needs to implement `run`" assert capture_io(fn -> b NoMix.run end) == "Could not load module NoMix, got: nofile\n" assert capture_io(fn -> b Exception.message/1 end) == "* defcallback message(t()) :: String.t()\n\n\n" end test "t helper" do assert capture_io(fn -> t IEx end) == "No type information for IEx was found\n" # Test that it shows at least two types assert Enum.count(capture_io(fn -> t Enum end) |> String.split("\n"), fn line -> String.starts_with? line, "@type" end) >= 2 assert "@type t() :: " <> _ = capture_io(fn -> t Enum.t end) assert capture_io(fn -> t Enum.t end) == capture_io(fn -> t Enum.t/0 end) assert "@opaque t()\n" = capture_io(fn -> t HashDict.t end) assert capture_io(fn -> t HashDict.t end) == capture_io(fn -> t HashDict.t/0 end) end test "s helper" do assert capture_io(fn -> s ExUnit end) == "No specification for ExUnit was found\n" # Test that it shows at least two specs assert Enum.count(capture_io(fn -> s Enum end) |> String.split("\n"), fn line -> String.starts_with? line, "@spec" end) >= 2 assert Enum.count(capture_io(fn -> s Enum.all? end) |> String.split("\n"), fn line -> String.starts_with? line, "@spec" end) >= 2 assert capture_io(fn -> s Enum.all?/1 end) == "@spec all?(t()) :: boolean()\n" assert capture_io(fn -> s struct end) == "@spec struct(module() | map(), Enum.t()) :: map()\n" end test "v helper" do assert "** (RuntimeError) v(0) is out of bounds" <> _ = capture_iex("v(0)") assert capture_iex("1\n2\nv(2)") == "1\n2\n2" assert capture_iex("1\n2\nv(2)") == capture_iex("1\n2\nv(-1)") assert capture_iex("1\n2\nv(2)") == capture_iex("1\n2\nv()") end test "flush helper" do assert capture_io(fn -> send self(), :hello; flush end) == ":hello\n" end test "pwd helper" do File.cd! iex_path, fn -> assert capture_io(fn -> pwd end) =~ ~r"lib[\\/]iex\n$" end end test "ls helper" do File.cd! iex_path, fn -> paths = capture_io(fn -> ls end) |> String.split |> Enum.map(&String.strip(&1)) assert "ebin" in paths assert "mix.exs" in paths assert capture_io(fn -> ls "~" end) == capture_io(fn -> ls System.user_home end) end end test "import_file helper" do with_file "dot-iex", "variable = :hello\nimport IO", fn -> assert "** (CompileError) iex:1: undefined function variable/0" <> _ = capture_iex("variable") assert "** (CompileError) iex:1: undefined function puts/1" <> _ = capture_iex("puts \"hi\"") assert capture_iex("import_file \"dot-iex\"\nvariable\nputs \"hi\"") == "nil\n:hello\nhi\n:ok" end end test "import_file nested" do dot = "parent = true\nimport_file \"dot-iex-1\"" dot_1 = "variable = :hello\nimport IO" with_file ["dot-iex", "dot-iex-1"], [dot, dot_1], fn -> assert "** (CompileError) iex:1: undefined function parent/0" <> _ = capture_iex("parent") assert "** (CompileError) iex:1: undefined function puts/1" <> _ = capture_iex("puts \"hi\"") assert capture_iex("import_file \"dot-iex\"\nvariable\nputs \"hi\"\nparent") == "nil\n:hello\nhi\n:ok\ntrue" end end test "import_file when the file is missing" do assert "nil" == capture_iex("import_file \"nonexistent\", optional: true") failing = capture_iex("import_file \"nonexistent\"") assert "** (File.Error) could not read file" <> _ = failing assert failing =~ "no such file or directory" end test "c helper" do assert_raise UndefinedFunctionError, ~r"undefined function: Sample\.run/0", fn -> Sample.run end filename = "sample.ex" with_file filename, test_module_code, fn -> assert c(filename) == [Sample] assert Sample.run == :run end after cleanup_modules([Sample]) end test "c helper with full path" do filename = "sample.ex" with_file filename, test_module_code, fn -> assert c(Path.expand(filename)) == [Sample] assert Sample.run == :run end after cleanup_modules([Sample]) end test "c helper multiple modules" do assert_raise UndefinedFunctionError, ~r"undefined function: Sample.run/0", fn -> Sample.run end filename = "sample.ex" with_file filename, test_module_code <> "\n" <> another_test_module, fn -> assert c(filename) |> Enum.sort == [Sample, Sample2] assert Sample.run == :run assert Sample2.hello == :world end after cleanup_modules([Sample, Sample2]) end test "c helper list" do assert_raise UndefinedFunctionError, ~r"undefined function: Sample.run/0", fn -> Sample.run end filenames = ["sample1.ex", "sample2.ex"] with_file filenames, [test_module_code, another_test_module], fn -> assert c(filenames) |> Enum.sort == [Sample, Sample2] assert Sample.run == :run assert Sample2.hello == :world end after cleanup_modules([Sample, Sample2]) end test "c helper erlang" do assert_raise UndefinedFunctionError, ~r"undefined function: :sample.hello/0", fn -> :sample.hello end filename = "sample.erl" with_file filename, erlang_module_code, fn -> assert c(filename) == [:sample] assert :sample.hello == :world end after cleanup_modules([:sample]) end test "c helper skips unknown files" do assert_raise UndefinedFunctionError, ~r"undefined function: :sample.hello/0", fn -> :sample.hello end filenames = ["sample.erl", "not_found.ex", "sample2.ex"] with_file filenames, [erlang_module_code, "", another_test_module], fn -> assert c(filenames) |> Enum.sort == [Sample2, :sample] assert :sample.hello == :world assert Sample2.hello == :world end after cleanup_modules([:sample, Sample2]) end test "l helper" do assert_raise UndefinedFunctionError, ~r"undefined function: Sample.run/0", fn -> Sample.run end assert l(:non_existent_module) == {:error, :nofile} filename = "sample.ex" with_file filename, test_module_code, fn -> assert c(filename) == [Sample] assert Sample.run == :run File.write! filename, "defmodule Sample do end" elixirc ["sample.ex"] assert l(Sample) == {:module, Sample} assert_raise UndefinedFunctionError, "undefined function: Sample.run/0", fn -> Sample.run end end after # Clean up the old version left over after l() cleanup_modules([Sample]) end test "r helper unavailable" do assert_raise ArgumentError, "could not load nor find module: :non_existent_module", fn -> r :non_existent_module end end test "r helper elixir" do assert_raise UndefinedFunctionError, ~r"undefined function: Sample.run/0 \(module Sample is not available\)", fn -> Sample.run end filename = "sample.ex" with_file filename, test_module_code, fn -> assert capture_io(:stderr, fn -> assert c(filename) == [Sample] assert Sample.run == :run File.write! filename, "defmodule Sample do end" assert {:reloaded, Sample, [Sample]} = r(Sample) assert_raise UndefinedFunctionError, "undefined function: Sample.run/0", fn -> Sample.run end end) =~ ~r"^.*?sample\.ex:1: warning: redefining module Sample\n$" end after # Clean up old version produced by the r helper cleanup_modules([Sample]) end test "r helper erlang" do assert_raise UndefinedFunctionError, ~r"undefined function: :sample.hello/0", fn -> :sample.hello end filename = "sample.erl" with_file filename, erlang_module_code, fn -> assert c(filename) == [:sample] assert :sample.hello == :world File.write!(filename, other_erlang_module_code) assert {:reloaded, :sample, [:sample]} = r(:sample) assert :sample.hello == :bye end after cleanup_modules([:sample]) end defp test_module_code do """ defmodule Sample do def run do :run end end """ end defp another_test_module do """ defmodule Sample2 do def hello do :world end end """ end defp erlang_module_code do """ -module(sample). -export([hello/0]). hello() -> world. """ end defp other_erlang_module_code do """ -module(sample). -export([hello/0]). hello() -> bye. """ end defp cleanup_modules(mods) do Enum.each mods, fn mod -> File.rm("#{mod}.beam") :code.purge(mod) true = :code.delete(mod) end end defp with_file(names, codes, fun) when is_list(names) and is_list(codes) do Enum.each Enum.zip(names, codes), fn {name, code} -> File.write! name, code end try do fun.() after Enum.each names, &File.rm/1 end end defp with_file(name, code, fun) do with_file(List.wrap(name), List.wrap(code), fun) end defp elixirc(args) do executable = Path.expand("../../../../bin/elixirc", __DIR__) System.cmd("#{executable}#{executable_extension}", args, [stderr_to_stdout: true]) end defp iex_path do Path.expand "../..", __DIR__ end if match? {:win32, _}, :os.type do defp executable_extension, do: ".bat" else defp executable_extension, do: "" end end elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/interaction_test.exs000066400000000000000000000121221254730255300243110ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IEx.InteractionTest do use IEx.Case ## Basic interaction test "whole output" do assert capture_io("IO.puts \"Hello world\"", fn -> IEx.Server.start([dot_iex_path: ""], {IEx, :dont_display_result, []}) end) =~ "Interactive Elixir (#{System.version}) - press Ctrl+C to exit (type h() ENTER for help)" <> "\niex(1)> Hello world\n:ok\niex(2)>" end test "empty input" do assert capture_iex("\n") == "nil" end test "normal input" do assert capture_iex("1 + 2") == "3" end test "multiple vars" do code = """ << a, b, c, d, e, f, g, h, i, j :: binary >> = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>> << a, b, c, d, e, f, g, h, i, x :: binary >> = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>> x """ assert capture_iex(code) =~ "10" end test "code escape" do code = """ 1 \\ + 2 """ assert capture_iex(code) =~ "3" end test "exception" do exception = Regex.escape("** (ArithmeticError) bad argument in arithmetic expression") assert capture_iex("1 + :atom\n:this_is_still_working") =~ ~r/^#{exception}.+\n:this_is_still_working$/s refute capture_iex("1 + :atom\n:this_is_still_working") =~ ~r/erl_eval/s end test "empty history at the start" do assert capture_iex("v(-1)") =~ "** (RuntimeError) v(-1) is out of bounds" end test "empty history at the start redux" do assert capture_iex("v(1)") =~ "** (RuntimeError) v(1) is out of bounds" end test "no break" do input = """ ["a b c """ assert capture_iex(input) == "" end test "break" do input = """ ["a b c #iex:break """ assert capture_iex(input) =~ "** (TokenMissingError) iex:1: incomplete expression" end test "invalid input" do assert capture_iex("if true do ) false end") =~ "** (SyntaxError) iex:1: unexpected token: \")\". \"do\" starting at" end test "module definition" do input = """ defmodule Sample do def foo, do: bar def bar, do: 13 end && Sample.foo """ assert capture_iex(input) =~ "13" after :code.purge(Sample) :code.delete(Sample) end test "prompt" do opts = [default_prompt: "prompt(%counter)>"] assert capture_iex("1\n", opts, [], true) == "prompt(1)> 1\nprompt(2)>" end unless match?({:win32, _}, :os.type) do test "color" do opts = [colors: [enabled: true, eval_result: [:red]]] assert capture_iex("1 + 2", opts) == "\e[31m3\e[0m" assert capture_iex("IO.ANSI.blue", opts) == "\e[31m\"\\e[34m\"\e[0m" end end test "inspect opts" do opts = [inspect: [binaries: :as_binaries, char_lists: :as_lists, structs: false, limit: 4]] assert capture_iex("<<45, 46, 47>>\n[45, 46, 47]\n%IO.Stream{}", opts) == "<<45, 46, 47>>\n[45, 46, 47]\n%{__struct__: IO.Stream, device: nil, line_or_bytes: :line, raw: true}" end test "history size" do opts = [history_size: 3] assert capture_iex("1\n2\n3\nv(1)", opts) == "1\n2\n3\n1" assert "1\n2\n3\n4\n** (RuntimeError) v(1) is out of bounds" <> _ = capture_iex("1\n2\n3\n4\nv(1)", opts) assert "1\n2\n3\n4\n** (RuntimeError) v(-4) is out of bounds" <> _ = capture_iex("1\n2\n3\n4\nv(-4)", opts) assert "1\n2\n3\n4\n2\n** (RuntimeError) v(2) is out of bounds" <> _ = capture_iex("1\n2\n3\n4\nv(2)\nv(2)", opts) end ## .iex file loading test "no .iex" do assert "** (CompileError) iex:1: undefined function my_variable/0" <> _ = capture_iex("my_variable") end test ".iex" do File.write!("dot-iex", "my_variable = 144") assert capture_iex("my_variable", [], [dot_iex_path: "dot-iex"]) == "144" after File.rm("dot-iex") end test "nested .iex" do File.write!("dot-iex-1", "nested_var = 13\nimport IO") File.write!("dot-iex", "import_file \"dot-iex-1\"\nmy_variable=14") input = "nested_var\nmy_variable\nputs \"hello\"" assert capture_iex(input, [], [dot_iex_path: "dot-iex"]) == "13\n14\nhello\n:ok" after File.rm("dot-iex-1") File.rm("dot-iex") end test "receive exit" do assert capture_iex("spawn_link(fn -> exit(:bye) end)") =~ ~r"\*\* \(EXIT from #PID<\d+\.\d+\.\d+>\) :bye" assert capture_iex("spawn_link(fn -> exit({:bye, [:world]}) end)") =~ ~r"\*\* \(EXIT from #PID<\d+\.\d+\.\d+>\) {:bye, \[:world\]}" end test "receive exit from exception" do # use exit/1 to fake an error so that an error message # is not sent to the error logger. content = capture_iex("spawn_link(fn -> exit({%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]}) end)") assert content =~ ~r"\*\* \(EXIT from #PID<\d+\.\d+\.\d+>\) an exception was raised:\n" assert content =~ ~r"\s{4}\*\* \(ArgumentError\) argument error\n" assert content =~ ~r"\s{8}:not_a_real_module\.function/0" end test "exit due to failed call" do assert capture_iex("exit({:bye, {:gen_server, :call, [self(), :hello]}})") =~ ~r"\*\* \(exit\) exited in: :gen_server\.call\(#PID<\d+\.\d+\.\d+>, :hello\)\n\s{4}\*\* \(EXIT\) :bye" end end elixir-lang-1.1.0~0.20150708/lib/iex/test/iex/server_test.exs000066400000000000000000000024141254730255300233030ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule IEx.ServerTest do use IEx.Case, async: true # Options test "prefix option" do assert capture_io(fn -> boot([prefix: "pry"]) end) =~ "pry(1)> " end test "env option" do assert capture_io("__ENV__.file", fn -> boot([env: __ENV__]) end) =~ "server_test.exs" end # Take over test "allows take over of the shell during boot" do assert capture_io("Y\na+b", fn -> server = self boot([], fn -> opts = [prefix: "dbg", binding: [a: 1, b: 2]] IEx.Server.take_over("iex:13", opts, 1000, server) end) end) =~ "dbg(1)> " end test "does not operate if callback during boot fails" do assert capture_io(fn -> boot([], fn -> exit(0) end) end) == "" end test "take over fails when there is no shell" do assert IEx.Server.take_over("iex:13", [], 10) == {:error, :no_iex} end test "pry wraps around take over" do require IEx assert capture_io(fn -> assert IEx.pry == {:error, :no_iex} end) =~ "Is an IEx shell running?" end # Helpers defp boot(opts, callback \\ fn -> end) do IEx.Server.start(Keyword.merge([dot_iex_path: ""], opts), {:erlang, :apply, [callback, []]}) end end elixir-lang-1.1.0~0.20150708/lib/iex/test/test_helper.exs000066400000000000000000000041341254730255300224700ustar00rootroot00000000000000:ok = Application.start(:iex) IEx.configure([colors: [enabled: false]]) ExUnit.start [trace: "--trace" in System.argv] defmodule IEx.Case do use ExUnit.CaseTemplate @moduledoc false # Provides convenience functions for testing IEx-related functionality. # Use this module inside your test module like this: # # defmodule IEx.InteractionTest do # use IEx.Case # # test :input do # assert capture_iex("1+2") == "3" # end # end # # The environment provided by capture_iex is mostly similar to the normal IEx # session, except colors are disabled by default and .iex files are not # loaded. # # You can provide your own IEx configuration and a path to a .iex file as # additional arguments to the capture_iex function. using do quote do import ExUnit.CaptureIO import unquote(__MODULE__) end end @iex_app_env [:default_prompt, :alive_prompt, :inspect, :colors, :history_size] setup do opts = Application.get_all_env(:iex) |> Keyword.take(@iex_app_env) on_exit fn -> Enum.each @iex_app_env, fn k -> Application.delete_env(:iex, k) end IEx.configure(opts) end :ok end @doc """ Starts an IEx eval loop, feeds it the provided input and returns produced output. The output is stripped of the first intro line and of any trailing whitespace. Options, if provided, will be set before the eval loop is started. If you provide server options, it will be passed to IEx.Server.start to be used in the normal .iex loading process. """ def capture_iex(input, options \\ [], server_options \\ [], capture_prompt \\ false) do IEx.configure(options) ExUnit.CaptureIO.capture_io([input: input, capture_prompt: capture_prompt], fn -> server_options = Keyword.put_new(server_options, :dot_iex_path, "") IEx.Server.start(server_options, {IEx, :dont_display_result, []}) end) |> strip_iex end defp strip_iex(string) do string |> strip_line # strip the greeting |> String.strip end defp strip_line(string) do Regex.replace ~r/\A.+?$/ms, string, "" end end elixir-lang-1.1.0~0.20150708/lib/logger/000077500000000000000000000000001254730255300171425ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/lib/000077500000000000000000000000001254730255300177105ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger.ex000066400000000000000000000374101254730255300215320ustar00rootroot00000000000000defmodule Logger do @moduledoc ~S""" A logger for Elixir applications. It includes many features: * Provides debug, info, warn and error levels. * Supports multiple backends which are automatically supervised when plugged into Logger. * Formats and truncates messages on the client to avoid clogging logger backends. * Alternates between sync and async modes to remain performant when required but also apply backpressure when under stress. * Wraps OTP's `error_logger` to prevent it from overflowing. ## Levels The supported levels are: * `:debug` - for debug-related messages * `:info` - for information of any kind * `:warn` - for warnings * `:error` - for errors ## Configuration Logger supports a wide range of configurations. This configuration is split in three categories: * Application configuration - must be set before the logger application is started * Runtime configuration - can be set before the logger application is started, but may be changed during runtime * Error logger configuration - configuration for the wrapper around OTP's `error_logger` ### Application configuration The following configuration must be set via config files before the logger application is started. * `:backends` - the backends to be used. Defaults to `[:console]`. See the "Backends" section for more information. * `:compile_time_purge_level` - purge all calls that have log level lower than the configured value at compilation time. This means the Logger call will be completely removed at compile time, accruing no overhead at runtime. Defaults to `:debug` and only applies to the `Logger.debug`, `Logger.info`, etc style of calls. For example, to configure the `:backends` and `compile_time_purge_level` in a `config/config.exs` file: config :logger, backends: [:console], compile_time_purge_level: :info ### Runtime Configuration All configuration below can be set via config files but also changed dynamically during runtime via `Logger.configure/1`. * `:level` - the logging level. Attempting to log any message with severity less than the configured level will simply cause the message to be ignored. Keep in mind that each backend may have its specific level, too. * `:utc_log` - when `true`, uses UTC in logs. By default it uses local time (i.e. it defaults to `false`). * `:truncate` - the maximum message size to be logged. Defaults to 8192 bytes. Note this configuration is approximate. Truncated messages will have `" (truncated)"` at the end. * `:sync_threshold` - if the logger manager has more than `sync_threshold` messages in its queue, Logger will change to sync mode, to apply backpressure to the clients. Logger will return to async mode once the number of messages in the queue is reduced to `sync_threshold * 0.75` messages. Defaults to 20 messages. For example, to configure the `:level` and `:truncate` in a `config/config.exs` file: config :logger, level: :warn, truncate: 4096 ### Error logger configuration The following configuration applies to the Logger wrapper around Erlang's `error_logger`. All the configurations below must be set before the logger application starts. * `:handle_otp_reports` - redirects OTP reports to Logger so they are formatted in Elixir terms. This uninstalls Erlang's logger that prints terms to terminal. Defaults to `true`. * `:handle_sasl_reports` - redirects supervisor, crash and progress reports to Logger so they are formatted in Elixir terms. This uninstalls `sasl`'s logger that prints these reports to the terminal. Defaults to `false`. * `:discard_threshold_for_error_logger` - a value that, when reached, triggers the error logger to discard messages. This value must be a positive number that represents the maximum number of messages accepted per second. Once above this threshold, the `error_logger` enters discard mode for the remainder of that second. Defaults to 500 messages. For example, to configure Logger to redirect all `error_logger` messages using a `config/config.exs` file: config :logger, handle_otp_reports: true, handle_sasl_reports: true Furthermore, Logger allows messages sent by Erlang's `error_logger` to be translated into an Elixir format via translators. Translators can be dynamically added at any time with the `add_translator/1` and `remove_translator/1` APIs. Check `Logger.Translator` for more information. ## Backends Logger supports different backends where log messages are written to. The available backends by default are: * `:console` - logs messages to the console (enabled by default) Developers may also implement their own backends, an option that is explored with detail below. The initial backends are loaded via the `:backends` configuration, which must be set before the logger application is started. ### Console backend The console backend logs message to the console. It supports the following options: * `:level` - the level to be logged by this backend. Note that messages are first filtered by the general `:level` configuration in `:logger` * `:format` - the format message used to print logs. Defaults to: `"$time $metadata[$level] $levelpad$message\n"` * `:metadata` - the metadata to be printed by `$metadata`. Defaults to an empty list (no metadata) * `:colors` - a keyword list of coloring options. The supported keys in the `:colors` keyword list are: * `:enabled` - boolean value that allows for switching the coloring on and off. Defaults to: `IO.ANSI.enabled?` * `:debug` - color for debug messages. Defaults to: `:cyan` * `:info` - color for info messages. Defaults to: `:normal` * `:warn` - color for warn messages. Defaults to: `:yellow` * `:error` - color for error messages. Defaults to: `:red` See the `IO.ANSI` module for a list of colors and attributes. Here is an example of how to configure the `:console` backend in a `config/config.exs` file: config :logger, :console, format: "\n$time $metadata[$level] $levelpad$message\n" metadata: [:user_id] You can read more about formatting in `Logger.Formatter`. ### Custom backends Any developer can create their own backend for Logger. Since Logger is an event manager powered by `GenEvent`, writing a new backend is a matter of creating an event handler, as described in the `GenEvent` module. From now on, we will be using the term "event handler" to refer to your custom backend, as we head into implementation details. Once Logger starts, it installs all event handlers under the `:backends` configuration into the Logger event manager. The event manager and all added event handlers are automatically supervised by Logger. Once initialized, the handler should be designed to handle events in the following format: {level, group_leader, {Logger, message, timestamp, metadata}} The level is one of `:debug`, `:info`, `:warn` or `:error`, as previously described, the group leader is the group leader of the process who logged the message, followed by a tuple starting with the atom `Logger`, the message as chardata, the timestamp and a keyword list of metadata. It is recommended that handlers ignore messages where the group leader is in a different node than the one the handler is installed. Furthermore, backends can be configured via the `configure_backend/2` function which requires event handlers to handle calls of the following format: {:configure, options} where options is a keyword list. The result of the call is the result returned by `configure_backend/2`. The recommended return value for successful configuration is `:ok`. It is recommended that backends support at least the following configuration values: * `level` - the logging level for that backend * `format` - the logging format for that backend * `metadata` - the metadata to include the backend Check the implementation for `Logger.Backends.Console` for examples on how to handle the recommendations in this section and how to process the existing options. """ @type backend :: GenEvent.handler @type message :: IO.chardata | String.Chars.t @type level :: :error | :info | :warn | :debug @levels [:error, :info, :warn, :debug] @metadata :logger_metadata @compile {:inline, __metadata__: 0} defp __metadata__ do Process.get(@metadata) || {true, []} end @doc """ Adds the given keyword list to the current process metadata. """ def metadata(dict) do {enabled, metadata} = __metadata__() Process.put(@metadata, {enabled, Keyword.merge(metadata, dict)}) :ok end @doc """ Reads the current process metadata. """ def metadata() do __metadata__() |> elem(1) end @doc """ Enables logging for the current process. Currently the only accepted process is self(). """ def enable(pid) when pid == self() do Process.put(@metadata, {true, metadata()}) :ok end @doc """ Disables logging for the current process. Currently the only accepted process is self(). """ def disable(pid) when pid == self() do Process.put(@metadata, {false, metadata()}) :ok end @doc """ Retrieves the logger level. The logger level can be changed via `configure/1`. """ @spec level() :: level def level() do %{level: level} = Logger.Config.__data__ level end @doc """ Compare log levels. Receives two log levels and compares the `left` against `right` and returns `:lt`, `:eq` or `:gt`. """ @spec compare_levels(level, level) :: :lt | :eq | :gt def compare_levels(level, level), do: :eq def compare_levels(left, right), do: if(level_to_number(left) > level_to_number(right), do: :gt, else: :lt) defp level_to_number(:debug), do: 0 defp level_to_number(:info), do: 1 defp level_to_number(:warn), do: 2 defp level_to_number(:error), do: 3 @doc """ Configures the logger. See the "Runtime Configuration" section in `Logger` module documentation for the available options. """ @valid_options [:compile_time_purge_level, :sync_threshold, :truncate, :level, :utc_log] def configure(options) do Logger.Config.configure(Dict.take(options, @valid_options)) end @doc """ Flushes the Logger. This basically guarantees all messages sent to the Logger prior to this call will be processed. This is useful for testing and it should not be called in production code. """ @spec flush :: :ok def flush do _ = GenEvent.which_handlers(:error_logger) _ = GenEvent.which_handlers(Logger) :ok end @doc """ Adds a new backend. ## Options * `:flush` - when `true`, guarantees all messages currently sent to both Logger and Erlang's `error_logger` are processed before the backend is added """ def add_backend(backend, opts \\ []) do _ = if opts[:flush], do: GenEvent.which_handlers(:error_logger) case Logger.Watcher.watch(Logger, Logger.Config.translate_backend(backend), backend) do {:ok, _} = ok -> Logger.Config.add_backend(backend) ok {:error, _} = error -> error end end @doc """ Removes a backend. ## Options * `:flush` - when `true`, guarantees all messages currently sent to both Logger and Erlang's `error_logger` are processed before the backend is removed """ def remove_backend(backend, opts \\ []) do _ = if opts[:flush], do: GenEvent.which_handlers(:error_logger) Logger.Config.remove_backend(backend) Logger.Watcher.unwatch(Logger, Logger.Config.translate_backend(backend)) end @doc """ Adds a new translator. """ def add_translator({mod, fun} = translator) when is_atom(mod) and is_atom(fun) do Logger.Config.add_translator(translator) end @doc """ Removes a translator. """ def remove_translator({mod, fun} = translator) when is_atom(mod) and is_atom(fun) do Logger.Config.remove_translator(translator) end @doc """ Configures the given backend. The backends needs to be started and running in order to be configured at runtime. """ @spec configure_backend(backend, Keyword.t) :: term def configure_backend(backend, options) when is_list(options) do GenEvent.call(Logger, Logger.Config.translate_backend(backend), {:configure, options}) end @doc """ Logs a message. Developers should use the macros `Logger.debug/2`, `Logger.warn/2`, `Logger.info/2` or `Logger.error/2` instead of this function as they automatically include caller metadata and can eliminate the Logger call altogether at compile time if desired. Use this function only when there is a need to log dynamically or you want to explicitly avoid embedding metadata. """ @spec log(level, message | (() -> message), Keyword.t) :: :ok | {:error, :noproc} | {:error, term} def log(level, chardata, metadata \\ []) when level in @levels and is_list(metadata) do case __metadata__() do {true, pdict} -> %{mode: mode, truncate: truncate, level: min_level, utc_log: utc_log?} = Logger.Config.__data__ if compare_levels(level, min_level) != :lt do tuple = {Logger, truncate(chardata, truncate), Logger.Utils.timestamp(utc_log?), [pid: self()] ++ metadata ++ pdict} try do notify(mode, {level, Process.group_leader(), tuple}) :ok rescue ArgumentError -> {:error, :noproc} catch :exit, reason -> {:error, reason} end else :ok end {false, _} -> :ok end end @doc """ Logs a warning. ## Examples Logger.warn "knob turned too far to the right" Logger.warn fn -> "expensive to calculate warning" end """ defmacro warn(chardata_or_fn, metadata \\ []) do macro_log(:warn, chardata_or_fn, metadata, __CALLER__) end @doc """ Logs some info. ## Examples Logger.info "mission accomplished" Logger.info fn -> "expensive to calculate info" end """ defmacro info(chardata_or_fn, metadata \\ []) do macro_log(:info, chardata_or_fn, metadata, __CALLER__) end @doc """ Logs an error. ## Examples Logger.error "oops" Logger.error fn -> "expensive to calculate error" end """ defmacro error(chardata_or_fn, metadata \\ []) do macro_log(:error, chardata_or_fn, metadata, __CALLER__) end @doc """ Logs a debug message. ## Examples Logger.debug "hello?" Logger.debug fn -> "expensive to calculate debug" end """ defmacro debug(chardata_or_fn, metadata \\ []) do macro_log(:debug, chardata_or_fn, metadata, __CALLER__) end defp macro_log(level, chardata, metadata, caller) do min_level = Application.get_env(:logger, :compile_time_purge_level, :debug) if compare_levels(level, min_level) != :lt do %{module: module, function: fun, line: line} = caller caller = [module: module, function: form_fa(fun), line: line] quote do Logger.log(unquote(level), unquote(chardata), unquote(caller) ++ unquote(metadata)) end else :ok end end defp truncate(data, n) when is_function(data, 0), do: Logger.Utils.truncate(data.(), n) defp truncate(data, n) when is_list(data) or is_binary(data), do: Logger.Utils.truncate(data, n) defp truncate(data, n), do: Logger.Utils.truncate(to_string(data), n) defp form_fa({name, arity}) do Atom.to_string(name) <> "/" <> Integer.to_string(arity) end defp form_fa(nil), do: nil defp notify(:sync, msg), do: GenEvent.sync_notify(Logger, msg) defp notify(:async, msg), do: GenEvent.notify(Logger, msg) end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/000077500000000000000000000000001254730255300211675ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/app.ex000066400000000000000000000044221254730255300223070ustar00rootroot00000000000000defmodule Logger.App do @moduledoc false use Application @doc false def start(_type, _args) do import Supervisor.Spec otp_reports? = Application.get_env(:logger, :handle_otp_reports) sasl_reports? = Application.get_env(:logger, :handle_sasl_reports) threshold = Application.get_env(:logger, :discard_threshold_for_error_logger) options = [strategy: :rest_for_one, name: Logger.Supervisor] children = [worker(GenEvent, [[name: Logger]]), worker(Logger.Watcher, [Logger, Logger.Config, []], [id: Logger.Config, function: :watcher]), supervisor(Logger.Watcher, [Logger.Config, :handlers, []]), worker(Logger.Watcher, [:error_logger, Logger.ErrorHandler, {otp_reports?, sasl_reports?, threshold}, :link], [id: Logger.ErrorHandler, function: :watcher])] config = Logger.Config.new() case Supervisor.start_link(children, options) do {:ok, sup} -> handlers = [error_logger_tty_h: otp_reports?, sasl_logger_tty_h: sasl_reports?] delete_handlers(handlers) {:ok, sup, config} {:error, _} = error -> Logger.Config.delete(config) error end end @doc false def stop(config) do Logger.Config.deleted_handlers() |> add_handlers() Logger.Config.delete(config) end @doc false def config_change(_changed, _new, _removed) do Logger.Config.configure([]) end @doc """ Stops the application without sending messages to error logger. """ def stop() do try do Logger.Config.deleted_handlers([]) catch :exit, {:noproc, _} -> {:error, {:not_started, :logger}} else deleted_handlers -> result = Application.stop(:logger) add_handlers(deleted_handlers) result end end defp delete_handlers(handlers) do deleted? = fn({handler, delete?}) -> delete? && :error_logger.delete_report_handler(handler) != {:error, :module_not_found} end [] = Enum.filter_map(handlers, deleted?, fn({handler, _}) -> handler end) |> Logger.Config.deleted_handlers() :ok end defp add_handlers(handlers) do Enum.each(handlers, &:error_logger.add_report_handler/1) end end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/backends/000077500000000000000000000000001254730255300227415ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/backends/console.ex000066400000000000000000000046071254730255300247500ustar00rootroot00000000000000defmodule Logger.Backends.Console do @moduledoc false use GenEvent def init(:console) do if Process.whereis(:user) do init({:user, []}) else {:error, :ignore} end end def init({device, opts}) do {:ok, configure(device, opts)} end def handle_call({:configure, options}, state) do {:ok, :ok, configure(state.device, options)} end def handle_event({_level, gl, _event}, state) when node(gl) != node() do {:ok, state} end def handle_event({level, _gl, {Logger, msg, ts, md}}, state) do if meet_level?(level, state.level) do log_event(level, msg, ts, md, state) end {:ok, state} end ## Helpers defp meet_level?(_lvl, nil), do: true defp meet_level?(lvl, min) do Logger.compare_levels(lvl, min) != :lt end defp configure(device, options) do config = Application.get_env(:logger, :console, []) |> configure_merge(options) if device === :user do Application.put_env(:logger, :console, config) end format = Keyword.get(config, :format) |> Logger.Formatter.compile level = Keyword.get(config, :level) metadata = Keyword.get(config, :metadata, []) colors = configure_colors(config) %{format: format, metadata: metadata, level: level, colors: colors, device: device} end defp configure_merge(env, options) do Keyword.merge(env, options, fn :colors, v1, v2 -> Keyword.merge(v1, v2) _, _v1, v2 -> v2 end) end defp configure_colors(config) do colors = Keyword.get(config, :colors, []) %{debug: Keyword.get(colors, :debug, :cyan), info: Keyword.get(colors, :info, :normal), warn: Keyword.get(colors, :warn, :yellow), error: Keyword.get(colors, :error, :red), enabled: Keyword.get(colors, :enabled, IO.ANSI.enabled?)} end defp log_event(level, msg, ts, md, %{colors: colors} = state) do output = format_event(level, msg, ts, md, state) |> color_event(level, colors) IO.write(state.device, output) end defp format_event(level, msg, ts, md, %{format: format, metadata: metadata}) do Logger.Formatter.format(format, level, msg, ts, Dict.take(md, metadata)) end defp color_event(data, _level, %{enabled: false}), do: data defp color_event(data, level, %{enabled: true} = colors) do [IO.ANSI.format_fragment(Map.fetch!(colors, level), true), data | IO.ANSI.reset] end end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/config.ex000066400000000000000000000121221254730255300227700ustar00rootroot00000000000000defmodule Logger.Config do @moduledoc false use GenEvent @name __MODULE__ @table __MODULE__ @data :__data__ @deleted_handlers :__deleted_handlers__ def start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def configure(options) do GenEvent.call(Logger, @name, {:configure, options}) end def add_translator(translator) do GenEvent.call(Logger, @name, {:add_translator, translator}) end def remove_translator(translator) do GenEvent.call(Logger, @name, {:remove_translator, translator}) end def handlers() do for backend <- backends() do {Logger, translate_backend(backend), backend} end end def backends() do GenEvent.call(Logger, @name, :backends) end def add_backend(backend) do GenEvent.call(Logger, @name, {:add_backend, backend}) end def remove_backend(backend) do GenEvent.call(Logger, @name, {:remove_backend, backend}) end def translate_backend(:console), do: Logger.Backends.Console def translate_backend(other), do: other def __data__() do try do :ets.lookup_element(@table, @data, 2) rescue ArgumentError -> raise "cannot use Logger, the :logger application is not running" else nil -> raise "cannot use Logger, the :logger application is not running" data -> data end end def deleted_handlers() do try do :ets.lookup_element(@table, @deleted_handlers, 2) rescue ArgumentError -> [] end end def deleted_handlers(handlers) do GenEvent.call(Logger, @name, {:deleted_handlers, handlers}) end def new() do tab = :ets.new(@table, [:named_table, :public, {:read_concurrency, true}]) true = :ets.insert_new(@table, [{@data, nil}, {@deleted_handlers, []}]) tab end def delete(@table) do :ets.delete(@table) end ## Callbacks def init(_) do # Use previous data if available in case this handler crashed. state = :ets.lookup_element(@table, @data, 2) || compute_state(:async) {:ok, state} end def handle_event({_type, gl, _msg} = event, state) when node(gl) != node() do # Cross node messages are always async which also # means this handler won't crash in case there is # no logger installed in the other node. GenEvent.notify({Logger, node(gl)}, event) {:ok, state} end def handle_event(_event, %{mode: mode} = state) do case compute_mode(state) do ^mode -> {:ok, state} new_mode -> {:ok, persist(%{state | mode: new_mode})} end end def handle_call(:backends, state) do {:ok, Application.get_env(:logger, :backends), state} end def handle_call({:configure, options}, state) do Enum.each options, fn {key, value} -> Application.put_env(:logger, key, value) end {:ok, :ok, compute_state(state.mode)} end def handle_call({:add_translator, translator}, state) do state = update_translators(state, fn t -> [translator|List.delete(t, translator)] end) {:ok, :ok, state} end def handle_call({:remove_translator, translator}, state) do state = update_translators(state, &List.delete(&1, translator)) {:ok, :ok, state} end def handle_call({:add_backend, backend}, state) do update_backends(&[backend|List.delete(&1, backend)]) {:ok, :ok, state} end def handle_call({:remove_backend, backend}, state) do update_backends(&List.delete(&1, backend)) {:ok, :ok, state} end def handle_call({:deleted_handlers, new}, state) do old = deleted_handlers() true = :ets.update_element(@table, @deleted_handlers, {2, new}) {:ok, old, state} end ## Helpers defp compute_mode(state) do {:message_queue_len, len} = Process.info(self(), :message_queue_len) cond do len > state.sync_threshold and state.mode == :async -> :sync len < state.async_threshold and state.mode == :sync -> :async true -> state.mode end end defp update_backends(fun) do backends = fun.(Application.get_env(:logger, :backends, [])) Application.put_env(:logger, :backends, backends) end defp update_translators(%{translators: translators} = state, fun) do translators = fun.(translators) Application.put_env(:logger, :translators, translators) persist %{state | translators: translators} end defp compute_state(mode) do level = Application.get_env(:logger, :level) utc_log = Application.get_env(:logger, :utc_log) truncate = Application.get_env(:logger, :truncate) translators = Application.get_env(:logger, :translators) sync_threshold = Application.get_env(:logger, :sync_threshold) async_threshold = trunc(sync_threshold * 0.75) state = %{level: level, mode: mode, truncate: truncate, utc_log: utc_log, sync_threshold: sync_threshold, async_threshold: async_threshold, translators: translators} case compute_mode(state) do ^mode -> persist(state) new_mode -> persist(%{state | mode: new_mode}) end end defp persist(state) do :ets.update_element(@table, @data, {2, state}) state end end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/error_handler.ex000066400000000000000000000115761254730255300243650ustar00rootroot00000000000000defmodule Logger.ErrorHandler do @moduledoc false use GenEvent require Logger def init({otp?, sasl?, threshold}) do # We store the logger PID in the state because when we are shutting # down the Logger application, the Logger process may be terminated # and then trying to reach it will lead to crashes. So we send a # message to a PID, instead of named process, to avoid crashes on # send since this handler will be removed soon by the supervisor. {:ok, %{otp: otp?, sasl: sasl?, threshold: threshold, logger: Process.whereis(Logger), last_length: 0, last_time: :os.timestamp, dropped: 0}} end ## Handle event def handle_event({_type, gl, _msg}, state) when node(gl) != node() do {:ok, state} end def handle_event(event, state) do state = check_threshold(state) log_event(event, state) {:ok, state} end ## Helpers defp log_event({:error, _gl, {pid, format, data}}, %{otp: true} = state), do: log_event(:error, :format, pid, {format, data}, state) defp log_event({:error_report, _gl, {pid, :std_error, format}}, %{otp: true} = state), do: log_event(:error, :report, pid, {:std_error, format}, state) defp log_event({:error_report, _gl, {pid, :supervisor_report, data}}, %{sasl: true} = state), do: log_event(:error, :report, pid, {:supervisor_report, data}, state) defp log_event({:error_report, _gl, {pid, :crash_report, data}}, %{sasl: true} = state), do: log_event(:error, :report, pid, {:crash_report, data}, state) defp log_event({:warning_msg, _gl, {pid, format, data}}, %{otp: true} = state), do: log_event(:warn, :format, pid, {format, data}, state) defp log_event({:warning_report, _gl, {pid, :std_warning, format}}, %{otp: true} = state), do: log_event(:warn, :report, pid, {:std_warning, format}, state) defp log_event({:info_msg, _gl, {pid, format, data}}, %{otp: true} = state), do: log_event(:info, :format, pid, {format, data}, state) defp log_event({:info_report, _gl, {pid, :std_info, format}}, %{otp: true} = state), do: log_event(:info, :report, pid, {:std_info, format}, state) defp log_event({:info_report, _gl, {pid, :progress, data}}, %{sasl: true} = state), do: log_event(:info, :report, pid, {:progress, data}, state) defp log_event(_, _state), do: :ok defp log_event(level, kind, pid, {type, _} = data, state) do %{level: min_level, truncate: truncate, utc_log: utc_log?, translators: translators} = Logger.Config.__data__ if Logger.compare_levels(level, min_level) != :lt && (message = translate(translators, min_level, level, kind, data, truncate)) do message = Logger.Utils.truncate(message, truncate) # Mode is always async to avoid clogging the error_logger meta = [pid: ensure_pid(pid), error_logger: ensure_type(type)] GenEvent.notify(state.logger, {level, Process.group_leader(), {Logger, message, Logger.Utils.timestamp(utc_log?), meta}}) end :ok end defp ensure_type(type) when is_atom(type), do: type defp ensure_type(_), do: :format defp ensure_pid(pid) when is_pid(pid), do: pid defp ensure_pid(_), do: self() defp check_threshold(%{last_time: last_time, last_length: last_length, dropped: dropped, threshold: threshold} = state) do {m, s, _} = current_time = :os.timestamp current_length = message_queue_length() cond do match?({^m, ^s, _}, last_time) and current_length - last_length > threshold -> count = drop_messages(current_time, 0) %{state | dropped: dropped + count, last_length: message_queue_length()} match?({^m, ^s, _}, last_time) -> state true -> _ = if dropped > 0 do Logger.warn "Logger dropped #{dropped} OTP/SASL messages as it " <> "exceeded the amount of #{threshold} messages/second" end %{state | dropped: 0, last_time: current_time, last_length: current_length} end end defp message_queue_length() do {:message_queue_len, len} = Process.info(self(), :message_queue_len) len end defp drop_messages({m, s, _} = last_time, count) do case :os.timestamp do {^m, ^s, _} -> receive do {:notify, _event} -> drop_messages(last_time, count + 1) after 0 -> count end _ -> count end end defp translate([{mod, fun}|t], min_level, level, kind, data, truncate) do case apply(mod, fun, [min_level, level, kind, data]) do {:ok, chardata} -> chardata :skip -> nil :none -> translate(t, min_level, level, kind, data, truncate) end end defp translate([], _min_level, _level, :format, {format, args}, truncate) do {format, args} = Logger.Utils.inspect(format, args, truncate) :io_lib.format(format, args) end defp translate([], _min_level, _level, :report, {_type, data}, _truncate) do Kernel.inspect(data) end end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/formatter.ex000066400000000000000000000106711254730255300235350ustar00rootroot00000000000000import Kernel, except: [inspect: 2] defmodule Logger.Formatter do @moduledoc ~S""" Conveniences for formatting data for logs. This module allows developers to specify a string that serves as template for log messages, for example: $time $metadata[$level] $message\n Will print error messages as: 18:43:12.439 user_id=13 [error] Hello\n The valid parameters you can use are: * `$time` - time the log message was sent * `$date` - date the log message was sent * `$message` - the log message * `$level` - the log level * `$node` - the node that prints the message * `$metadata` - user controlled data presented in `"key=val key2=val2"` format * `$levelpad` - set to a single space if level is 4 characters long, otherwise set to the empty space. Used to align the message after level. Backends typically allow developers to supply such control strings via configuration files. This module provides `compile/1`, which compiles the string into a format for fast operations at runtime and `format/5` to format the compiled pattern into an actual IO data. ## Metadata Metadata to be sent to the Logger can be read and written with the `Logger.metadata/0` and `Logger.metadata/1` functions. For example, you can set `Logger.metadata([user_id: 13])` to add user_id metadata to the current process. The user can configure the backend to chose which metadata it wants to print and it will replace the `$metadata` value. """ @type time :: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59, 0..999}} @type pattern :: :date | :level | :levelpad | :message | :metadata | :node | :time @valid_patterns [:time, :date, :message, :level, :node, :metadata, :levelpad] @default_pattern "\n$time $metadata[$level] $levelpad$message\n" @doc ~S""" Compiles a format string into an array that the `format/5` can handle. Check the module doc for documentation on the valid parameters. If you pass `nil`, it defaults to: `$time $metadata [$level] $levelpad$message\n` If you would like to make your own custom formatter simply pass `{module, function}` to `compile/1` and the rest is handled. iex> Logger.Formatter.compile("$time $metadata [$level] $message\n") [:time, " ", :metadata, " [", :level, "] ", :message, "\n"] """ @spec compile(binary | nil) :: [pattern | binary] @spec compile({atom, atom}) :: {atom, atom} def compile(nil), do: compile(@default_pattern) def compile({mod, fun}) when is_atom(mod) and is_atom(fun), do: {mod, fun} def compile(str) do for part <- Regex.split(~r/(?)\$[a-z]+(?)/, str, on: [:head, :tail], trim: true) do case part do "$" <> code -> compile_code(String.to_atom(code)) _ -> part end end end defp compile_code(key) when key in @valid_patterns, do: key defp compile_code(key) when is_atom(key) do raise(ArgumentError, message: "$#{key} is an invalid format pattern.") end @doc """ Takes a compiled format and injects the, level, timestamp, message and metadata listdict and returns a properly formatted string. """ @spec format({atom, atom} | [pattern | binary], Logger.level, Logger.message, time, Keyword.t) :: IO.chardata def format({mod, fun}, level, msg, ts, md) do apply(mod, fun, [level, msg, ts, md]) end def format(config, level, msg, ts, md) do for c <- config do output(c, level, msg, ts, md) end end defp output(:message, _, msg, _, _), do: msg defp output(:date, _, _, {date, _time}, _), do: Logger.Utils.format_date(date) defp output(:time, _, _, {_date, time}, _), do: Logger.Utils.format_time(time) defp output(:level, level, _, _, _), do: Atom.to_string(level) defp output(:node, _, _, _, _), do: Atom.to_string(node()) defp output(:metadata, _, _, _, []), do: "" defp output(:metadata, _, _, _, meta) do Enum.map(meta, fn {key, val} -> [to_string(key), ?=, metadata(val), ?\s] end) end defp output(:levelpad, level, _, _, _) do levelpad(level) end defp output(other, _, _, _, _), do: other defp levelpad(:debug), do: "" defp levelpad(:info), do: " " defp levelpad(:warn), do: " " defp levelpad(:error), do: "" defp metadata(pid) when is_pid(pid) do :erlang.pid_to_list(pid) end defp metadata(pid) when is_reference(pid) do '#Ref' ++ rest = :erlang.ref_to_list(pid) rest end defp metadata(other), do: to_string(other) end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/translator.ex000066400000000000000000000324721254730255300237260ustar00rootroot00000000000000defmodule Logger.Translator do @moduledoc """ Default translation for Erlang log messages. Logger allows developers to rewrite log messages provided by Erlang applications into a format more compatible with Elixir log messages by providing a translator. A translator is simply a tuple containing a module and a function that can be added and removed via the `Logger.add_translator/1` and `Logger.remove_translator/1` functions and is invoked for every Erlang message above the minimum log level with four arguments: * `min_level` - the current Logger level * `level` - the level of the message being translator * `kind` - if the message is a report or a format * `message` - the message to format. If it is a report, it is a tuple with `{report_type, report_data}`, if it is a format, it is a tuple with `{format_message, format_args}` The function must return: * `{:ok, chardata}` - if the message was translated with its translation * `:skip` - if the message is not meant to be translated nor logged * `:none` - if there is no translation, which triggers the next translator See the function `translate/4` in this module for an example implementation and the default messages translated by Logger. """ # TODO: Remove name_or_id checks once we support only OTP >18.0 def translate(min_level, level, kind, message) def translate(min_level, :error, :format, message) do case message do {'** Generic server ' ++ _, [name, last, state, reason]} -> msg = ["GenServer #{inspect name} terminating" | format_stop(reason)] if min_level == :debug do msg = [msg, "\nLast message: #{inspect last}" | "\nState: #{inspect state}"] end {:ok, msg} {'** gen_event handler ' ++ _, [name, manager, last, state, reason]} -> msg = ["GenEvent handler #{inspect name} installed in #{inspect manager} terminating" | format_stop(reason)] if min_level == :debug do msg = [msg, "\nLast message: #{inspect last}" | "\nState: #{inspect state}"] end {:ok, msg} {'** Task ' ++ _, [name, starter, function, args, reason]} -> msg = ["Task #{inspect name} started from #{inspect starter} terminating", format_stop(reason), "\nFunction: #{inspect function}" | "\n Args: #{inspect args}"] {:ok, msg} {'Error in process ' ++ _, [pid, {reason, stack}]} -> msg = ["Process ", inspect(pid), " raised an exception" | format(:error, reason, stack)] {:ok, msg} _ -> :none end end def translate(_min_level, :info, :report, {:std_info, [application: app, exited: reason, type: _type]}) do {:ok, "Application #{app} exited: #{Application.format_error(reason)}"} end def translate(min_level, :error, :report, {:supervisor_report, data}) do translate_supervisor(min_level, data) end def translate(min_level, :error, :report, {:crash_report, data}) do translate_crash(min_level, data) end def translate(min_level, :info, :report, {:progress, data}) do translate_progress(min_level, data) end def translate(_min_level, _level, _kind, _message) do :none end defp translate_supervisor(min_level, [supervisor: sup, errorContext: context, reason: reason, offender: [{:pid, pid}, {name_or_id, name} | offender]]) when is_pid(pid) and context !== :shutdown and name_or_id in [:name, :id] do {:ok, ["Child ", inspect(name), " of Supervisor ", sup_name(sup), ?\s, sup_context(context), "\n** (exit) ", offender_reason(reason, context), "\nPid: ", inspect(pid) | child_info(min_level, offender)]} end defp translate_supervisor(min_level, [supervisor: sup, errorContext: context, reason: reason, offender: [{:pid, _pid}, {name_or_id, name} | offender]]) when name_or_id in [:name, :id] do {:ok, ["Child ", inspect(name), " of Supervisor ", sup_name(sup), ?\s, sup_context(context), "\n** (exit) ", offender_reason(reason, context) | child_info(min_level, offender)]} end defp translate_supervisor(min_level, [supervisor: sup, errorContext: context, reason: reason, offender: [{:pid, pid} | offender]]) do {:ok, ["Child of Supervisor ", sup_name(sup), ?\s, sup_context(context), "\n** (exit) ", offender_reason(reason, context), "\nPid: ", inspect(pid) | child_info(min_level, offender)]} end defp translate_supervisor(min_level, [supervisor: sup, errorContext: context, reason: reason, offender: [{:nb_children, n}, {name_or_id, name} | offender]]) when name_or_id in [:name, :id] do {:ok, ["Children ", inspect(name), " of Supervisor ", sup_name(sup), ?\s, sup_context(context), "\n** (exit) ", offender_reason(reason, context), "\nNumber: ", inspect(n) | child_info(min_level, offender)]} end defp translate_supervisor(_min_level, _other), do: :none defp translate_progress(_min_level, [application: app, started_at: node_name]) do {:ok, ["Application ", to_string(app), " started at " | inspect(node_name)]} end defp translate_progress(min_level, [supervisor: sup, started: [{:pid, pid}, {name_or_id, name} | started]]) when name_or_id in [:name, :id] do {:ok, ["Child ", inspect(name), " of Supervisor ", sup_name(sup), " started", "\nPid: ", inspect(pid) | child_info(min_level, started)]} end defp translate_progress(min_level, [supervisor: sup, started: [{:pid, pid} | started]]) do {:ok, ["Child of Supervisor ", sup_name(sup), " started", "\nPid: ", inspect(pid) | child_info(min_level, started)]} end defp translate_progress(_min_level, _other), do: :none defp sup_name({:local, name}), do: inspect(name) defp sup_name({:global, name}), do: inspect(name) defp sup_name({:via, _mod, name}), do: inspect(name) defp sup_name({pid, mod}), do: [inspect(pid), " (", inspect(mod), ?)] defp sup_context(:start_error), do: "failed to start" defp sup_context(:child_terminated), do: "terminated" defp sup_context(:shutdown), do: "caused shutdown" defp sup_context(:shutdown_error), do: "shutdown abnormally" defp child_info(min_level, [{:mfargs, {mod, fun, args}} | debug]) do ["\nStart Call: ", format_mfa(mod, fun, args) | child_debug(min_level, debug)] end defp child_info(min_level, [{:mfa, {mod, fun, args}} | debug]) do ["\nStart Call: ", format_mfa(mod, fun, args) | child_debug(min_level, debug)] end defp child_info(min_level, [{:mod, mod} | debug]) do ["\nStart Module: ", inspect(mod) | child_debug(min_level, debug)] end defp child_debug(:debug, [restart_type: restart, shutdown: shutdown, child_type: type]) do ["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown), "\nType: ", inspect(type)] end defp child_debug(_min_level, _child) do [] end # If start call raises reason will be of form {:EXIT, reason} defp offender_reason({:EXIT, reason}, :start_error) do Exception.format_exit(reason) end defp offender_reason(reason, _context) do Exception.format_exit(reason) end defp translate_crash(min_level, [[{:initial_call, _} = initial_call, {:pid, pid}, {:registered_name, name}, {:error_info, {kind, exception, stack}} | crashed], linked]) do {:ok, ["Process ", crash_name(pid, name), " terminating", format(kind, exception, stack), crash_info(min_level, [initial_call | crashed]) | crash_linked(min_level, linked)]} end defp translate_crash(min_level, [[{:pid, pid}, {:registered_name, name}, {:error_info, {kind, exception, stack}} | crashed], linked]) do {:ok, ["Process ", crash_name(pid, name), " terminating", format(kind, exception, stack), crash_info(min_level, crashed), crash_linked(min_level, linked)]} end defp crash_name(pid, []), do: inspect(pid) defp crash_name(pid, name), do: [inspect(name), " (", inspect(pid), ?)] defp crash_info(min_level, info, prefix \\ [?\n]) defp crash_info(min_level, [{:initial_call, {mod, fun, args}} | info], prefix) do [prefix, "Initial Call: ", crash_call(mod, fun, args) | crash_info(min_level, info, prefix)] end defp crash_info(min_level, [{:current_function, {mod, fun, args}} | info], prefix) do [prefix, "Current Call: ", crash_call(mod, fun, args) | crash_info(min_level, info, prefix)] end defp crash_info(min_level, [{:current_function, []} | info], prefix) do crash_info(min_level, info, prefix) end defp crash_info(min_level, [{:ancestors, ancestors} | debug], prefix) do [prefix, "Ancestors: ", inspect(ancestors) | crash_debug(min_level, debug, prefix)] end defp crash_call(mod, fun, arity) when is_integer(arity) do format_mfa(mod, fun, arity) end defp crash_call(mod, fun, args) do format_mfa(mod, fun, length(args)) end defp crash_debug(:debug, [messages: msgs, links: links, dictionary: dict, trap_exit: trap, status: status, heap_size: heap_size, stack_size: stack_size, reductions: reductions], prefix) do [prefix, "Messages: ", inspect(msgs), prefix, "Links: ", inspect(links), prefix, "Dictionary: ", inspect(dict), prefix, "Trapping Exits: ", inspect(trap), prefix, "Status: ", inspect(status), prefix, "Heap Size: ", inspect(heap_size), prefix, "Stack Size: ", inspect(stack_size), prefix, "Reductions: ", inspect(reductions)] end defp crash_debug(_min_level, _info, _prefix) do [] end defp crash_linked(_min_level, []), do: [] defp crash_linked(min_level, neighbours) do Enum.reduce(neighbours, "\nNeighbours:", fn({:neighbour, info}, acc) -> [acc | crash_neighbour(min_level, info)] end) end defp crash_neighbour(min_level, [{:pid, pid}, {:registered_name, []} | info]) do indent = " " [?\n, indent, inspect(pid) | crash_info(min_level, info, [?\n, indent | indent])] end defp crash_neighbour(min_level, [{:pid, pid}, {:registered_name, name} | info]) do indent = " " [?\n, indent, inspect(name), " (", inspect(pid), ")" | crash_info(min_level, info, [?\n, indent | indent])] end defp format_stop({maybe_exception, [_ | _ ] = maybe_stacktrace} = reason) do try do format_stacktrace(maybe_stacktrace) catch :error, _ -> format_stop_banner(reason) else formatted_stacktrace -> [format_stop_banner(maybe_exception, maybe_stacktrace) | formatted_stacktrace] end end defp format_stop(reason) do format_stop_banner(reason) end defp format_stop_banner(reason) do ["\n** (stop) " | Exception.format_exit(reason)] end # OTP process rewrite the :undef error to these reasons when logging @gen_undef [:"module could not be loaded", :"function not exported"] defp format_stop_banner(undef, [{mod, fun, args, _info} | _ ] = stacktrace) when undef in @gen_undef and is_atom(mod) and is_atom(fun) do cond do is_list(args) -> format_undef(mod, fun, length(args), undef, stacktrace) is_integer(args) -> format_undef(mod, fun, args, undef, stacktrace) true -> format_stop_banner(undef) end end defp format_stop_banner(reason, stacktrace) do if Exception.exception?(reason) do [?\n | Exception.format_banner(:error, reason, stacktrace)] else case Exception.normalize(:error, reason, stacktrace) do %ErlangError{} -> format_stop_banner(reason) exception -> [?\n | Exception.format_banner(:error, exception, stacktrace)] end end end defp format_undef(mod, fun, arity, undef, stacktrace) do opts = [module: mod, function: fun, arity: arity, reason: undef] exception = UndefinedFunctionError.exception(opts) [?\n | Exception.format_banner(:error, exception, stacktrace)] end defp format(kind, payload, stacktrace) do [?\n, Exception.format_banner(kind, payload, stacktrace) | format_stacktrace(stacktrace)] end defp format_stacktrace(stacktrace) do for entry <- stacktrace do [<<"\n ">> | Exception.format_stacktrace_entry(entry)] end end defp format_mfa(mod, fun, :undefined), do: [inspect(mod), ?., to_string(fun) | "/?"] defp format_mfa(mod, fun, args), do: Exception.format_mfa(mod, fun, args) end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/utils.ex000066400000000000000000000217051254730255300226720ustar00rootroot00000000000000defmodule Logger.Utils do @moduledoc false @doc """ Truncates a char data into n bytes. There is a chance we truncate in the middle of a grapheme cluster but we never truncate in the middle of a binary codepoint. For this reason, truncation is not exact. """ @spec truncate(IO.chardata, non_neg_integer) :: IO.chardata def truncate(chardata, n) when n >= 0 do {chardata, n} = truncate_n(chardata, n) if n >= 0, do: chardata, else: [chardata, " (truncated)"] end defp truncate_n(_, n) when n < 0 do {"", n} end defp truncate_n(binary, n) when is_binary(binary) do remaining = n - byte_size(binary) if remaining < 0 do # There is a chance we are cutting at the wrong # place so we need to fix the binary. {fix_binary(binary_part(binary, 0, n)), remaining} else {binary, remaining} end end defp truncate_n(int, n) when int in 0..127, do: {int, n-1} defp truncate_n(int, n) when int in 127..0x07FF, do: {int, n-2} defp truncate_n(int, n) when int in 0x800..0xFFFF, do: {int, n-3} defp truncate_n(int, n) when int >= 0x10000 and is_integer(int), do: {int, n-4} defp truncate_n(list, n) when is_list(list) do truncate_n_list(list, n, []) end defp truncate_n_list(_, n, acc) when n < 0 do {:lists.reverse(acc), n} end defp truncate_n_list([h|t], n, acc) do {h, n} = truncate_n(h, n) truncate_n_list(t, n, [h|acc]) end defp truncate_n_list([], n, acc) do {:lists.reverse(acc), n} end defp truncate_n_list(t, n, acc) do {t, n} = truncate_n(t, n) {:lists.reverse(acc, t), n} end defp fix_binary(binary) do # Use a thirteen-bytes offset to look back in the binary. # This should allow at least two codepoints of 6 bytes. suffix_size = min(byte_size(binary), 13) prefix_size = byte_size(binary) - suffix_size <> = binary prefix <> fix_binary(suffix, "") end defp fix_binary(<>, acc) do acc <> <> <> fix_binary(t, "") end defp fix_binary(<>, acc) do fix_binary(t, <>) end defp fix_binary(<<>>, _acc) do <<>> end @doc """ Receives a format string and arguments and replace `~p`, `~P`, `~w` and `~W` by its inspected variants. """ def inspect(format, args, truncate, opts \\ %Inspect.Opts{}) def inspect(format, args, truncate, opts) when is_atom(format) do do_inspect(Atom.to_char_list(format), args, truncate, opts) end def inspect(format, args, truncate, opts) when is_binary(format) do do_inspect(:binary.bin_to_list(format), args, truncate, opts) end def inspect(format, args, truncate, opts) when is_list(format) do do_inspect(format, args, truncate, opts) end defp do_inspect(format, [], _truncate, _opts), do: {format, []} defp do_inspect(format, args, truncate, opts) do # A pre-pass that removes binaries from # arguments according to the truncate limit. {args, _} = Enum.map_reduce(args, truncate, fn arg, acc -> if is_binary(arg) do truncate_n(arg, acc) else {arg, acc} end end) do_inspect(format, args, [], [], opts) end defp do_inspect([?~|t], args, used_format, used_args, opts) do {t, args, cc_format, cc_args} = collect_cc(:width, t, args, [?~], [], opts) do_inspect(t, args, cc_format ++ used_format, cc_args ++ used_args, opts) end defp do_inspect([h|t], args, used_format, used_args, opts), do: do_inspect(t, args, [h|used_format], used_args, opts) defp do_inspect([], [], used_format, used_args, _opts), do: {:lists.reverse(used_format), :lists.reverse(used_args)} ## width defp collect_cc(:width, [?-|t], args, used_format, used_args, opts), do: collect_value(:width, t, args, [?-|used_format], used_args, opts, :precision) defp collect_cc(:width, t, args, used_format, used_args, opts), do: collect_value(:width, t, args, used_format, used_args, opts, :precision) ## precision defp collect_cc(:precision, [?.|t], args, used_format, used_args, opts), do: collect_value(:precision, t, args, [?.|used_format], used_args, opts, :pad_char) defp collect_cc(:precision, t, args, used_format, used_args, opts), do: collect_cc(:pad_char, t, args, used_format, used_args, opts) ## pad char defp collect_cc(:pad_char, [?.,?*|t], [arg|args], used_format, used_args, opts), do: collect_cc(:encoding, t, args, [?*,?.|used_format], [arg|used_args], opts) defp collect_cc(:pad_char, [?.,p|t], args, used_format, used_args, opts), do: collect_cc(:encoding, t, args, [p,?.|used_format], used_args, opts) defp collect_cc(:pad_char, t, args, used_format, used_args, opts), do: collect_cc(:encoding, t, args, used_format, used_args, opts) ## encoding defp collect_cc(:encoding, [?l|t], args, used_format, used_args, opts), do: collect_cc(:done, t, args, [?l|used_format], used_args, %{opts | char_lists: false}) defp collect_cc(:encoding, [?t|t], args, used_format, used_args, opts), do: collect_cc(:done, t, args, [?t|used_format], used_args, opts) defp collect_cc(:encoding, t, args, used_format, used_args, opts), do: collect_cc(:done, t, args, used_format, used_args, opts) ## done defp collect_cc(:done, [?W|t], [data, limit|args], _used_format, _used_args, opts), do: collect_inspect(t, args, data, %{opts | limit: limit, width: :infinity}) defp collect_cc(:done, [?w|t], [data|args], _used_format, _used_args, opts), do: collect_inspect(t, args, data, %{opts | width: :infinity}) defp collect_cc(:done, [?P|t], [data, limit|args], _used_format, _used_args, opts), do: collect_inspect(t, args, data, %{opts | limit: limit}) defp collect_cc(:done, [?p|t], [data|args], _used_format, _used_args, opts), do: collect_inspect(t, args, data, opts) defp collect_cc(:done, [h|t], args, used_format, used_args, _opts) do {args, used_args} = collect_cc(h, args, used_args) {t, args, [h|used_format], used_args} end defp collect_cc(?x, [a,prefix|args], used), do: {args, [prefix, a|used]} defp collect_cc(?X, [a,prefix|args], used), do: {args, [prefix, a|used]} defp collect_cc(?s, [a|args], used), do: {args, [a|used]} defp collect_cc(?e, [a|args], used), do: {args, [a|used]} defp collect_cc(?f, [a|args], used), do: {args, [a|used]} defp collect_cc(?g, [a|args], used), do: {args, [a|used]} defp collect_cc(?b, [a|args], used), do: {args, [a|used]} defp collect_cc(?B, [a|args], used), do: {args, [a|used]} defp collect_cc(?+, [a|args], used), do: {args, [a|used]} defp collect_cc(?#, [a|args], used), do: {args, [a|used]} defp collect_cc(?c, [a|args], used), do: {args, [a|used]} defp collect_cc(?i, [a|args], used), do: {args, [a|used]} defp collect_cc(?~, args, used), do: {args, used} defp collect_cc(?n, args, used), do: {args, used} defp collect_inspect(t, args, data, opts) do data = data |> Inspect.Algebra.to_doc(opts) |> Inspect.Algebra.format(opts.width) {t, args, 'st~', [data]} end defp collect_value(current, [?*|t], [arg|args], used_format, used_args, opts, next) when is_integer(arg) do collect_cc(next, t, args, [?*|used_format], [arg|used_args], put_value(opts, current, arg)) end defp collect_value(current, [c|t], args, used_format, used_args, opts, next) when is_integer(c) and c >= ?0 and c <= ?9 do {t, c} = collect_value([c|t], []) collect_cc(next, t, args, c ++ used_format, used_args, put_value(opts, current, c |> :lists.reverse |> List.to_integer)) end defp collect_value(_current, t, args, used_format, used_args, opts, next), do: collect_cc(next, t, args, used_format, used_args, opts) defp collect_value([c|t], buffer) when is_integer(c) and c >= ?0 and c <= ?9, do: collect_value(t, [c|buffer]) defp collect_value(other, buffer), do: {other, buffer} defp put_value(opts, key, value) do if Map.has_key?(opts, key) do Map.put(opts, key, value) else opts end end @doc """ Returns a timestamp that includes milliseconds. """ def timestamp(utc_log?) do {_, _, micro} = now = :os.timestamp() {date, {hours, minutes, seconds}} = case utc_log? do true -> :calendar.now_to_universal_time(now) false -> :calendar.now_to_local_time(now) end {date, {hours, minutes, seconds, div(micro, 1000)}} end @doc """ Formats time as chardata. """ def format_time({hh, mi, ss, ms}) do [pad2(hh), ?:, pad2(mi), ?:, pad2(ss), ?., pad3(ms)] end @doc """ Formats date as chardata. """ def format_date({yy, mm, dd}) do [Integer.to_string(yy), ?-, pad2(mm), ?-, pad2(dd)] end defp pad3(int) when int < 10, do: [?0, ?0, Integer.to_string(int)] defp pad3(int) when int < 100, do: [?0, Integer.to_string(int)] defp pad3(int), do: Integer.to_string(int) defp pad2(int) when int < 10, do: [?0, Integer.to_string(int)] defp pad2(int), do: Integer.to_string(int) end elixir-lang-1.1.0~0.20150708/lib/logger/lib/logger/watcher.ex000066400000000000000000000057141254730255300231710ustar00rootroot00000000000000defmodule Logger.Watcher do @moduledoc false require Logger use GenServer @name Logger.Watcher @doc """ Starts the watcher supervisor. """ def start_link(m, f, a) do import Supervisor.Spec child = worker(__MODULE__, [], [function: :watcher, restart: :transient]) options = [strategy: :simple_one_for_one, name: @name] case Supervisor.start_link([child], options) do {:ok, _} = ok -> _ = for {mod, handler, args} <- apply(m, f, a) do {:ok, _} = watch(mod, handler, args) end ok {:error, _} = error -> error end end @doc """ Removes the given handler. """ def unwatch(mod, handler) do GenEvent.remove_handler(mod, handler, :ok) end @doc """ Watches the given handler as part of the watcher supervision tree. """ def watch(mod, handler, args) do case Supervisor.start_child(@name, [mod, handler, args]) do {:ok, _pid} = result -> result {:error, _reason} = error -> error end end @doc """ Starts a watcher server. This is useful when there is a need to start a handler outside of the handler supervision tree. """ def watcher(mod, handler, args, style \\ :monitor) do GenServer.start_link(__MODULE__, {mod, handler, args, style}) end ## Callbacks @doc false def init({mod, handler, args, :monitor}) do ref = Process.monitor(mod) res = GenEvent.add_mon_handler(mod, handler, args) do_init(res, mod, handler, ref) end def init({mod, handler, args, :link}) do res = :gen_event.add_sup_handler(mod, handler, args) do_init(res, mod, handler, nil) end defp do_init(res, mod, handler, ref) do case res do :ok -> {:ok, {mod, handler, ref}} {:error, :ignore} -> # Can't return :ignore as a transient child under a simple_one_for_one. # Instead return ok and then immediately exit normally - using a fake # message. send(self(), {:gen_event_EXIT, handler, :normal}) {:ok, {mod, handler, ref}} {:error, reason} -> {:stop, reason} end end @doc false def handle_info({:gen_event_EXIT, handler, reason}, {_, handler, _} = state) when reason in [:normal, :shutdown] do {:stop, reason, state} end def handle_info({:gen_event_EXIT, handler, reason}, {mod, handler, _} = state) do _ = Logger.error "GenEvent handler #{inspect handler} installed at #{inspect mod}\n" <> "** (exit) #{format_exit(reason)}" {:stop, reason, state} end def handle_info({:DOWN, ref, _, _, reason}, {mod, handler, ref} = state) do _ = Logger.error "GenEvent handler #{inspect handler} installed at #{inspect mod}\n" <> "** (exit) #{format_exit(reason)}" {:stop, reason, state} end def handle_info(_msg, state) do {:noreply, state} end defp format_exit({:EXIT, reason}), do: Exception.format_exit(reason) defp format_exit(reason), do: Exception.format_exit(reason) end elixir-lang-1.1.0~0.20150708/lib/logger/mix.exs000066400000000000000000000012451254730255300204620ustar00rootroot00000000000000defmodule Logger.Mixfile do use Mix.Project def project do [app: :logger, version: System.version, build_per_environment: false] end def application do [registered: [Logger, Logger.Supervisor, Logger.Watcher], mod: {Logger.App, []}, env: [level: :debug, utc_log: false, truncate: 8096, backends: [:console], translators: [{Logger.Translator, :translate}], sync_threshold: 20, handle_otp_reports: true, handle_sasl_reports: false, compile_time_purge_level: :debug, discard_threshold_for_error_logger: 500, console: []]] end end elixir-lang-1.1.0~0.20150708/lib/logger/test/000077500000000000000000000000001254730255300201215ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/000077500000000000000000000000001254730255300214005ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/backends/000077500000000000000000000000001254730255300231525ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/backends/console_test.exs000066400000000000000000000057151254730255300264040ustar00rootroot00000000000000defmodule Logger.Backends.ConsoleTest do use Logger.Case require Logger setup do on_exit fn -> :ok = Logger.configure_backend(:console, [format: nil, level: nil, metadata: [], colors: [enabled: false]]) end end test "does not start when there is no user" do :ok = Logger.remove_backend(:console) user = Process.whereis(:user) try do Process.unregister(:user) assert GenEvent.add_handler(Logger, Logger.Backends.Console, :console) == {:error, :ignore} after Process.register(user, :user) end after {:ok, _} = Logger.add_backend(:console) end test "can configure format" do Logger.configure_backend(:console, format: "$message [$level]") assert capture_log(fn -> Logger.debug("hello") end) =~ "hello [debug]" end test "can configure metadata" do Logger.configure_backend(:console, format: "$metadata$message", metadata: [:user_id]) assert capture_log(fn -> Logger.debug("hello") end) =~ "hello" Logger.metadata(user_id: 11) Logger.metadata(user_id: 13) assert capture_log(fn -> Logger.debug("hello") end) =~ "user_id=13 hello" end test "metadata defaults" do Logger.configure_backend(:console, format: "$metadata", metadata: [:module, :function, :line]) %{module: mod, function: {name, arity}, line: line} = __ENV__ assert capture_log(fn -> Logger.debug("hello") end) =~ "module=#{mod} function=#{name}/#{arity} line=#{line + 3}" end test "can configure level" do Logger.configure_backend(:console, level: :info) assert capture_log(fn -> Logger.debug("hello") end) == "" end test "can configure colors" do Logger.configure_backend(:console, [format: "$message", colors: [enabled: true]]) assert capture_log(fn -> Logger.debug("hello") end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset() Logger.configure_backend(:console, [colors: [debug: :magenta]]) assert capture_log(fn -> Logger.debug("hello") end) == IO.ANSI.magenta() <> "hello" <> IO.ANSI.reset() assert capture_log(fn -> Logger.info("hello") end) == IO.ANSI.normal() <> "hello" <> IO.ANSI.reset() Logger.configure_backend(:console, [colors: [info: :cyan]]) assert capture_log(fn -> Logger.info("hello") end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset() assert capture_log(fn -> Logger.warn("hello") end) == IO.ANSI.yellow() <> "hello" <> IO.ANSI.reset() Logger.configure_backend(:console, [colors: [warn: :cyan]]) assert capture_log(fn -> Logger.warn("hello") end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset() assert capture_log(fn -> Logger.error("hello") end) == IO.ANSI.red() <> "hello" <> IO.ANSI.reset() Logger.configure_backend(:console, [colors: [error: :cyan]]) assert capture_log(fn -> Logger.error("hello") end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset() end end elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/error_handler_test.exs000066400000000000000000000045361254730255300260160ustar00rootroot00000000000000defmodule Logger.ErrorHandlerTest do use Logger.Case test "survives after crashes" do assert capture_log(fn -> :error_logger.info_msg("~p~n", []) wait_for_handler(:error_logger, Logger.ErrorHandler) end) =~ "[error] GenEvent handler Logger.ErrorHandler installed at :error_logger\n" <> "** (exit) an exception was raised:" assert error_log(:info_msg, "~p~n", [:hello]) =~ msg("[info] :hello") end test "survives after Logger exit" do Process.whereis(Logger) |> Process.exit(:kill) wait_for_logger() wait_for_handler(:error_logger, Logger.ErrorHandler) assert error_log(:info_msg, "~p~n", [:hello]) =~ msg("[info] :hello") end test "formats error_logger info message" do assert error_log(:info_msg, "hello", []) =~ msg("[info] hello") assert error_log(:info_msg, "~p~n", [:hello]) =~ msg("[info] :hello") end test "formats error_logger info report" do assert error_log(:info_report, "hello") =~ msg("[info] \"hello\"") assert error_log(:info_report, :hello) =~ msg("[info] :hello") assert error_log(:info_report, :special, :hello) == "" end test "formats error_logger error message" do assert error_log(:error_msg, "hello", []) =~ msg("[error] hello") assert error_log(:error_msg, "~p~n", [:hello]) =~ msg("[error] :hello") end test "formats error_logger error report" do assert error_log(:error_report, "hello") =~ msg("[error] \"hello\"") assert error_log(:error_report, :hello) =~ msg("[error] :hello") assert error_log(:error_report, :special, :hello) == "" end if :erlang.system_info(:otp_release) >= '18' do test "formats error_logger warning message" do assert error_log(:warning_msg, "hello", []) =~ msg("[warn] hello") assert error_log(:warning_msg, "~p~n", [:hello]) =~ msg("[warn] :hello") end test "formats error_logger warning report" do assert error_log(:warning_report, "hello") =~ msg("[warn] \"hello\"") assert error_log(:warning_report, :hello) =~ msg("[warn] :hello") assert error_log(:warning_report, :special, :hello) == "" end end defp error_log(fun, format) do do_error_log(fun, [format]) end defp error_log(fun, format, args) do do_error_log(fun, [format, args]) end defp do_error_log(fun, args) do capture_log(fn -> apply(:error_logger, fun, args) end) end end elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/formatter_test.exs000066400000000000000000000050611254730255300251650ustar00rootroot00000000000000defmodule Logger.FormatterTest do use Logger.Case, async: true doctest Logger.Formatter import Logger.Formatter defmodule CompileMod do def format(_level, _msg, _ts, _md) do true end end test "compile/1 with nil" do assert compile(nil) == ["\n", :time, " ", :metadata, "[", :level, "] ", :levelpad, :message, "\n"] end test "compile/1 with str" do assert compile("$level $time $date $metadata $message $node") == Enum.intersperse([:level, :time, :date, :metadata, :message, :node], " ") assert_raise ArgumentError, "$bad is an invalid format pattern.", fn -> compile("$bad $good") end end test "compile/1 with {mod, fun}" do assert compile({CompileMod, :format}) == {CompileMod, :format} end test "format with {mod, fun}" do assert format({CompileMod, :format}, nil, nil, nil, nil) == true end test "format with format string" do compiled = compile("[$level] $message") assert format(compiled, :error, "hello", nil, []) == ["[", "error", "] ", "hello"] compiled = compile("$node") assert format(compiled, :error, nil, nil, []) == [Atom.to_string(node())] compiled = compile("$metadata") assert IO.chardata_to_string(format(compiled, :error, nil, nil, [meta: :data])) == "meta=data " assert IO.chardata_to_string(format(compiled, :error, nil, nil, [meta: :data, pid: :erlang.list_to_pid('<0.123.4>')])) == "meta=data pid=<0.123.4> " # Hack to get the same predictable reference for every test run. ref = <<131, 114, 0, 3, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0>> |> :erlang.binary_to_term assert "#Reference<0.0.0.80>" == inspect(ref) # ensure the deserialization worked correctly assert IO.chardata_to_string(format(compiled, :error, nil, nil, [meta: :data, ref: ref])) == "meta=data ref=<0.0.0.80> " assert IO.chardata_to_string(format(compiled, :error, nil, nil, [])) == "" timestamp = {{2014, 12, 30}, {12, 6, 30, 100}} compiled = compile("$date $time") assert IO.chardata_to_string(format(compiled, :error, nil, timestamp, [])) == "2014-12-30 12:06:30.100" end test "padding takes account of length of level" do compiled = compile("[$level] $levelpad $message") assert format(compiled, :error, "hello", nil, []) == ["[", "error", "] ", "", " ", "hello"] assert format(compiled, :info, "hello", nil, []) == ["[", "info", "] ", " ", " ", "hello"] end end elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/translator_test.exs000066400000000000000000000464421254730255300253630ustar00rootroot00000000000000defmodule Logger.TranslatorTest do use Logger.Case import Supervisor.Spec defmodule MyGenServer do use GenServer def handle_call(:error, _, _) do raise "oops" end end defmodule MyGenEvent do use GenEvent def handle_call(:error, _) do raise "oops" end end defmodule MyBridge do @behaviour :supervisor_bridge def init(reason) do {:ok, pid} = Task.start_link(Kernel, :exit, [reason]) {:ok, pid, pid} end def terminate(_reason, pid) do Process.exit(pid, :shutdown) end end setup_all do sasl_reports? = Application.get_env(:logger, :handle_sasl_reports, false) Application.put_env(:logger, :handle_sasl_reports, true) # Restart the app but change the level before to avoid warnings level = Logger.level() Logger.configure(level: :error) Logger.App.stop() Application.start(:logger) Logger.configure(level: level) on_exit(fn() -> Application.put_env(:logger, :handle_sasl_reports, sasl_reports?) Logger.App.stop() Application.start(:logger) end) end test "translates GenServer crashes" do {:ok, pid} = GenServer.start(MyGenServer, :ok) assert capture_log(:info, fn -> catch_exit(GenServer.call(pid, :error)) end) =~ """ [error] GenServer #{inspect pid} terminating ** (RuntimeError) oops """ end test "translates GenServer crashes on debug" do {:ok, pid} = GenServer.start(MyGenServer, :ok) assert capture_log(:debug, fn -> catch_exit(GenServer.call(pid, :error)) end) =~ ~r""" \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating \*\* \(RuntimeError\) oops .* Last message: :error State: :ok """s end test "translates GenEvent crashes" do {:ok, pid} = GenEvent.start() :ok = GenEvent.add_handler(pid, MyGenEvent, :ok) assert capture_log(:info, fn -> GenEvent.call(pid, MyGenEvent, :error) end) =~ """ [error] GenEvent handler Logger.TranslatorTest.MyGenEvent installed in #{inspect pid} terminating ** (RuntimeError) oops """ end test "translates GenEvent crashes on debug" do {:ok, pid} = GenEvent.start() :ok = GenEvent.add_handler(pid, MyGenEvent, :ok) assert capture_log(:debug, fn -> GenEvent.call(pid, MyGenEvent, :error) end) =~ ~r""" \[error\] GenEvent handler Logger.TranslatorTest.MyGenEvent installed in #PID<\d+\.\d+\.\d+> terminating \*\* \(RuntimeError\) oops .* Last message: :error State: :ok """s end test "translates Task crashes" do {:ok, pid} = Task.start_link(__MODULE__, :task, [self()]) assert capture_log(fn -> ref = Process.monitor(pid) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(RuntimeError\) oops .* Function: &Logger.TranslatorTest.task\/1 Args: \[#PID<\d+\.\d+\.\d+>\] """s end test "translates Task undef module crash" do assert capture_log(fn -> {:ok, pid} = Task.start(:module_does_not_exist, :undef, []) ref = Process.monitor(pid) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(UndefinedFunctionError\) undefined function: :module_does_not_exist.undef/0 \(module :module_does_not_exist is not available\) .* Function: &:module_does_not_exist.undef/0 Args: \[\] """s end test "translates Task undef function crash" do assert capture_log(fn -> {:ok, pid} = Task.start(__MODULE__, :undef, []) ref = Process.monitor(pid) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(UndefinedFunctionError\) undefined function: Logger.TranslatorTest.undef/0 .* Function: &Logger.TranslatorTest.undef/0 Args: \[\] """s end test "translates Task raising ErlangError" do assert capture_log(fn -> exception = try do :erlang.error(:foo) rescue x -> x end {:ok, pid} = Task.start(:erlang, :error, [exception]) ref = Process.monitor(pid) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(ErlangError\) erlang error: :foo .* Function: &:erlang\.error/1 Args: \[%ErlangError{.*}\] """s end test "translates Task raising erlang badarg error" do assert capture_log(fn -> {:ok, pid} = Task.start(:erlang, :error, [:badarg]) ref = Process.monitor(pid) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(ArgumentError\) argument error .* Function: &:erlang\.error/1 Args: \[:badarg\] """s end test "translates Task exiting abnormally" do assert capture_log(fn -> {:ok, pid} = Task.start(:erlang, :exit, [:abnormal]) ref = Process.monitor(pid) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> terminating \*\* \(stop\) :abnormal .* Function: &:erlang\.exit/1 Args: \[:abnormal\] """s end test "translates application stop" do assert capture_log(fn -> :ok = Application.start(:eex) Application.stop(:eex) end) =~ """ Application eex exited: :stopped """ end test "translates application start" do assert capture_log(fn -> Application.start(:eex) Application.stop(:eex) end) =~ """ Application eex started at #{inspect(node())} """ end test "translates :proc_lib crashes" do {:ok, pid} = Task.start_link(__MODULE__, :task, [self()]) assert capture_log(:info, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Process #PID<\d+\.\d+\.\d+> terminating \*\* \(exit\) an exception was raised: \*\* \(RuntimeError\) oops .* Initial Call: Logger.TranslatorTest.task/1 Ancestors: \[#PID<\d+\.\d+\.\d+>\] """s end test "translates Process crashes" do if :erlang.system_info(:otp_release) >= '18' do assert capture_log(:info, fn -> {_, ref} = spawn_monitor(fn() -> raise "oops" end) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) # Even though the monitor has been received the emulator may not have # sent the message to the error logger :timer.sleep(200) end) =~ ~r""" \[error\] Process #PID<\d+\.\d+\.\d+>\ raised an exception \*\* \(RuntimeError\) oops """ end end test "translates :proc_lib crashes with name" do {:ok, pid} = Task.start_link(__MODULE__, :task, [self(), fn() -> Process.register(self(), __MODULE__) raise "oops" end]) assert capture_log(:info, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Process Logger.TranslatorTest \(#PID<\d+\.\d+\.\d+>\) terminating \*\* \(exit\) an exception was raised: \*\* \(RuntimeError\) oops .* Initial Call: Logger.TranslatorTest.task/2 Ancestors: \[#PID<\d+\.\d+\.\d+>\] """s end test "translates :proc_lib crashes without initial call" do {:ok, pid} = Task.start_link(__MODULE__, :task, [self(), fn() -> Process.delete(:"$initial_call") raise "oops" end]) assert capture_log(:info, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[error\] Process #PID<\d+\.\d+\.\d+> terminating \*\* \(exit\) an exception was raised: \*\* \(RuntimeError\) oops .* Ancestors: \[#PID<\d+\.\d+\.\d+>\] """s end test "translates :proc_lib crashes with neighbour" do {:ok, pid} = Task.start_link(__MODULE__, :sub_task, [self()]) assert capture_log(:info, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" Ancestors: \[#PID<\d+\.\d+\.\d+>\] Neighbours: #PID<\d+\.\d+\.\d+> Initial Call: :timer.sleep/1 Current Call: :timer.sleep/1 Ancestors: \[#PID<\d+\.\d+\.\d+>, #PID<\d+\.\d+\.\d+>\] """ end M test "translates :proc_lib crashes with neighbour with name" do {:ok, pid} = Task.start_link(__MODULE__, :sub_task, [self(), fn(pid2) -> Process.register(pid2, __MODULE__) raise "oops" end]) assert capture_log(:info, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" Ancestors: \[#PID<\d+\.\d+\.\d+>\] Neighbours: Logger.TranslatorTest \(#PID<\d+\.\d+\.\d+>\) Initial Call: :timer.sleep/1 Current Call: :timer.sleep/1 Ancestors: \[#PID<\d+\.\d+\.\d+>, #PID<\d+\.\d+\.\d+>\] """ end test "translates :proc_lib crashes on debug" do {:ok, pid} = Task.start_link(__MODULE__, :task, [self()]) assert capture_log(:debug, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" Ancestors: \[#PID<\d+\.\d+\.\d+>\] Messages: \[:message\] Links: \[\] Dictionary: \[\] Trapping Exits: false Status: :running Heap Size: \d+ Stack Size: \d+ Reductions: \d+ """ end test "translates :proc_lib crashes with neighbour on debug" do {:ok, pid} = Task.start_link(__MODULE__, :sub_task, [self()]) assert capture_log(:debug, fn -> ref = Process.monitor(pid) send(pid, :message) send(pid, :go) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" Ancestors: \[#PID<\d+\.\d+\.\d+>, #PID<\d+\.\d+\.\d+>\] Messages: \[\] Links: \[#PID<\d+\.\d+\.\d+>\] Dictionary: \[\] Trapping Exits: false Status: :waiting Heap Size: \d+ Stack Size: \d+ Reductions: \d+ """ end test "translates Supervisor progress" do {:ok, pid} = Supervisor.start_link([], [strategy: :one_for_one]) assert capture_log(:info, fn -> ref = Process.monitor(pid) Supervisor.start_child(pid, worker(Task, [:timer, :sleep, [500]])) Process.exit(pid, :normal) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[info\] Child Task of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) started Pid: #PID<\d+\.\d+\.\d+> Start Call: Task.start_link\(:timer, :sleep, \[500\]\) """ end test "translates Supervisor progress with name" do {:ok, pid} = Supervisor.start_link([], [strategy: :one_for_one, name: __MODULE__]) assert capture_log(:info, fn -> ref = Process.monitor(pid) Supervisor.start_child(pid, worker(Task, [:timer, :sleep, [500]])) Process.exit(pid, :normal) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[info\] Child Task of Supervisor Logger.TranslatorTest started """ {:ok, pid} = Supervisor.start_link([], [strategy: :one_for_one, name: {:global, __MODULE__}]) assert capture_log(:info, fn -> ref = Process.monitor(pid) Supervisor.start_child(pid, worker(Task, [:timer, :sleep, [500]])) Process.exit(pid, :normal) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[info\] Child Task of Supervisor Logger.TranslatorTest started """ {:ok, pid} = Supervisor.start_link([], [strategy: :one_for_one, name: {:via, :global, __MODULE__}]) assert capture_log(:info, fn -> ref = Process.monitor(pid) Supervisor.start_child(pid, worker(Task, [:timer, :sleep, [500]])) Process.exit(pid, :normal) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" \[info\] Child Task of Supervisor Logger.TranslatorTest started """ end test "translates Supervisor progress on debug" do {:ok, pid} = Supervisor.start_link([], [strategy: :one_for_one]) assert capture_log(:debug, fn -> ref = Process.monitor(pid) Supervisor.start_child(pid, worker(Task, [:timer, :sleep, [500]])) Process.exit(pid, :normal) receive do: ({:DOWN, ^ref, _, _, _} -> :ok) end) =~ ~r""" Start Call: Task.start_link\(:timer, :sleep, \[500\]\) Restart: :permanent Shutdown: 5000 Type: :worker """ end test "translates Supervisor reports start error" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) Supervisor.start_link([worker(__MODULE__, [], [function: :error])], [strategy: :one_for_one]) receive do: ({:EXIT, _, {:shutdown, {:failed_to_start_child, _, _}}} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Child Logger.TranslatorTest of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) failed to start \*\* \(exit\) :stop Start Call: Logger.TranslatorTest.error\(\) """ end test "translates Supervisor reports start error with raise" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) Supervisor.start_link([worker(__MODULE__, [], [function: :undef])], [strategy: :one_for_one]) receive do: ({:EXIT, _, {:shutdown, {:failed_to_start_child, _, _}}} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Child Logger.TranslatorTest of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) failed to start \*\* \(exit\) an exception was raised: \*\* \(UndefinedFunctionError\) undefined function: Logger.TranslatorTest.undef/0 .* Start Call: Logger.TranslatorTest.undef\(\) """s end test "translates Supervisor reports terminated" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) {:ok, pid} = Supervisor.start_link([worker(Task, [Kernel, :exit, [:stop]])], [strategy: :one_for_one, max_restarts: 0]) receive do: ({:EXIT, ^pid, _} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Child Task of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) terminated \*\* \(exit\) :stop Pid: #PID<\d+\.\d+\.\d+> Start Call: Task.start_link\(Kernel, :exit, \[:stop\]\) """ end test "translates Supervisor reports max restarts shutdown" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) {:ok, pid} = Supervisor.start_link([worker(Task, [Kernel, :exit, [:stop]])], [strategy: :one_for_one, max_restarts: 0]) receive do: ({:EXIT, ^pid, _} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Child Task of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) caused shutdown \*\* \(exit\) :reached_max_restart_intensity Start Call: Task.start_link\(Kernel, :exit, \[:stop\]\) """ end test "translates Supervisor reports abnormal shutdown" do assert capture_log(:info, fn -> {:ok, pid} = Supervisor.start_link([worker(__MODULE__, [], [function: :abnormal])], [strategy: :one_for_one]) :ok = Supervisor.terminate_child(pid, __MODULE__) end) =~ ~r""" \[error\] Child Logger.TranslatorTest of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) shutdown abnormally \*\* \(exit\) :stop Pid: #PID<\d+\.\d+\.\d+> Start Call: Logger.TranslatorTest.abnormal\(\) """ end test "translates Supervisor reports abnormal shutdown on debug" do assert capture_log(:debug, fn -> {:ok, pid} = Supervisor.start_link([worker(__MODULE__, [], [function: :abnormal, restart: :permanent, shutdown: 5000])], [strategy: :one_for_one]) :ok = Supervisor.terminate_child(pid, __MODULE__) end) =~ ~r""" \*\* \(exit\) :stop Pid: #PID<\d+\.\d+\.\d+> Start Call: Logger.TranslatorTest.abnormal\(\) Restart: :permanent Shutdown: 5000 Type: :worker """ end test "translates Supervisor reports abnormal shutdown in simple_one_for_one" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) {:ok, pid} = Supervisor.start_link([worker(__MODULE__, [], [function: :abnormal])], [strategy: :simple_one_for_one]) {:ok, _pid2} = Supervisor.start_child(pid, []) Process.exit(pid, :normal) receive do: ({:EXIT, ^pid, _} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Children Logger.TranslatorTest of Supervisor #PID<\d+\.\d+\.\d+> \(Supervisor\.Default\) shutdown abnormally \*\* \(exit\) :stop Number: 1 Start Call: Logger.TranslatorTest.abnormal\(\) """ end test "translates :supervisor_bridge progress" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) {:ok, pid} = :supervisor_bridge.start_link(MyBridge, :normal) receive do: ({:EXIT, ^pid, _} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[info\] Child of Supervisor #PID<\d+\.\d+\.\d+> \(Logger\.TranslatorTest\.MyBridge\) started Pid: #PID<\d+\.\d+\.\d+> Start Call: Logger.TranslatorTest.MyBridge.init\(:normal\) """ end test "translates :supervisor_bridge reports" do assert capture_log(:info, fn -> trap = Process.flag(:trap_exit, true) {:ok, pid} = :supervisor_bridge.start_link(MyBridge, :stop) receive do: ({:EXIT, ^pid, _} -> :ok) Process.flag(:trap_exit, trap) end) =~ ~r""" \[error\] Child of Supervisor #PID<\d+\.\d+\.\d+> \(Logger\.TranslatorTest\.MyBridge\) terminated \*\* \(exit\) :stop Pid: #PID<\d+\.\d+\.\d+> Start Module: Logger.TranslatorTest.MyBridge """ end test "handles :undefined MFA properly" do children = [Supervisor.Spec.worker(GenServer, [], restart: :temporary)] opts = [strategy: :simple_one_for_one] {:ok, sup} = Supervisor.start_link(children, opts) assert capture_log(:info, fn -> {:ok, pid} = Supervisor.start_child(sup, [MyGenServer, []]) catch_exit(GenServer.call(pid, :error)) [] = Supervisor.which_children(sup) end) =~ "Start Call: GenServer.start_link/?" end def task(parent, fun \\ (fn() -> raise "oops" end)) do Process.unlink(parent) receive do: (:go -> fun.()) end def sub_task(parent, fun \\ (fn(_) -> raise "oops" end)) do Process.unlink(parent) {:ok, pid} = Task.start_link(:timer, :sleep, [500]) receive do: (:go -> fun.(pid)) end def error(), do: {:error, :stop} def abnormal() do :proc_lib.start_link(__MODULE__, :abnormal_init, []) end def abnormal_init() do Process.flag(:trap_exit, true) :proc_lib.init_ack({:ok, self()}) receive do: ({:EXIT, _, _} -> exit(:stop)) end end elixir-lang-1.1.0~0.20150708/lib/logger/test/logger/utils_test.exs000066400000000000000000000063501254730255300243240ustar00rootroot00000000000000defmodule Logger.UtilsTest do use Logger.Case, async: true import Logger.Utils import Kernel, except: [inspect: 2] defp inspect(format, args), do: Logger.Utils.inspect(format, args, 10) test "truncate/2" do # ASCII binaries assert truncate("foo", 4) == "foo" assert truncate("foo", 3) == "foo" assert truncate("foo", 2) == ["fo", " (truncated)"] # UTF-8 binaries assert truncate("olá", 2) == ["ol", " (truncated)"] assert truncate("olá", 3) == ["ol", " (truncated)"] assert truncate("olá", 4) == "olá" assert truncate("ááááá:", 10) == ["ááááá", " (truncated)"] assert truncate("áááááá:", 10) == ["ááááá", " (truncated)"] # Charlists assert truncate('olá', 2) == ['olá', " (truncated)"] assert truncate('olá', 3) == ['olá', " (truncated)"] assert truncate('olá', 4) == 'olá' # Chardata assert truncate('ol' ++ "á", 2) == ['ol' ++ "", " (truncated)"] assert truncate('ol' ++ "á", 3) == ['ol' ++ "", " (truncated)"] assert truncate('ol' ++ "á", 4) == 'ol' ++ "á" end test "inspect/2 formats" do assert inspect('~p', [1]) == {'~ts', [["1"]]} assert inspect("~p", [1]) == {'~ts', [["1"]]} assert inspect(:"~p", [1]) == {'~ts', [["1"]]} end test "inspect/2 sigils" do assert inspect('~10.10tp', [1]) == {'~ts', [["1"]]} assert inspect('~-10.10tp', [1]) == {'~ts', [["1"]]} assert inspect('~10.10lp', [1]) == {'~ts', [["1"]]} assert inspect('~10.10x~p~n', [1, 2, 3]) == {'~10.10x~ts~n', [1, 2, ["3"]]} end test "inspect/2 with modifier t has no effect (as it is the default)" do assert inspect('~tp', [1]) == {'~ts', [["1"]]} assert inspect('~tw', [1]) == {'~ts', [["1"]]} end test "inspect/2 with modifier l always prints lists" do assert inspect('~lp', ['abc']) == {'~ts', [["[", "97", ",", " ", "98", ",", " ", "99", "]"]]} assert inspect('~lw', ['abc']) == {'~ts', [["[", "97", ",", " ", "98", ",", " ", "99", "]"]]} end test "inspect/2 with modifier for width" do assert inspect('~5lp', ['abc']) == {'~ts', [["[", "97", ",", "\n ", "98", ",", "\n ", "99", "]"]]} assert inspect('~5lw', ['abc']) == {'~ts', [["[", "97", ",", " ", "98", ",", " ", "99", "]"]]} end test "inspect/2 with modifier for limit" do assert inspect('~5lP', ['abc', 2]) == {'~ts', [["[", "97", ",", "\n ", "98", ",", "\n ", "...", "]"]]} assert inspect('~5lW', ['abc', 2]) == {'~ts', [["[", "97", ",", " ", "98", ",", " ", "...", "]"]]} end test "inspect/2 truncates binaries" do assert inspect('~ts', ["abcdeabcdeabcdeabcde"]) == {'~ts', ["abcdeabcde"]} assert inspect('~ts~ts~ts', ["abcdeabcde", "abcde", "abcde"]) == {'~ts~ts~ts', ["abcdeabcde", "", ""]} end test "timestamp" do assert {{_, _, _}, {_, _, _, _}} = timestamp(true) end test "format_date" do date = {2015, 1, 30} assert format_date(date) == ["2015", ?-, [?0, "1"], ?-, "30"] end test "format_time" do time = {12, 30, 10, 1} assert format_time(time) == ["12", ?:, "30", ?:, "10", ?., [?0, ?0, "1"]] time = {12, 30, 10, 10} assert format_time(time) == ["12", ?:, "30", ?:, "10", ?., [?0, "10"]] end end elixir-lang-1.1.0~0.20150708/lib/logger/test/logger_test.exs000066400000000000000000000147661254730255300231760ustar00rootroot00000000000000defmodule LoggerTest do use Logger.Case require Logger test "add_translator/1 and remove_translator/1" do defmodule CustomTranslator do def t(:debug, :info, :format, {'hello: ~p', [:ok]}) do :skip end def t(:debug, :info, :format, {'world: ~p', [:ok]}) do {:ok, "rewritten"} end def t(_, _, _, _) do :none end end assert Logger.add_translator({CustomTranslator, :t}) assert capture_log(fn -> :error_logger.info_msg('hello: ~p', [:ok]) end) == "" assert capture_log(fn -> :error_logger.info_msg('world: ~p', [:ok]) end) =~ "\[info\] rewritten" after assert Logger.remove_translator({CustomTranslator, :t}) end test "add_backend/1 and remove_backend/1" do assert :ok = Logger.remove_backend(:console) assert Application.get_env(:logger, :backends) == [] assert Logger.remove_backend(:console) == {:error, :not_found} assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) == "" assert {:ok, _pid} = Logger.add_backend(:console) assert Application.get_env(:logger, :backends) == [:console] assert Logger.add_backend(:console) == {:error, :already_present} assert Application.get_env(:logger, :backends) == [:console] end test "add_backend/1 with {module, id}" do defmodule MyBackend do use GenEvent def init({MyBackend, :hello}) do {:ok, :hello} end end assert {:ok, _} = Logger.add_backend({MyBackend, :hello}) assert {:error, :already_present} = Logger.add_backend({MyBackend, :hello}) assert :ok = Logger.remove_backend({MyBackend, :hello}) end test "level/0" do assert Logger.level == :debug end test "enable/1 and disable/1" do assert Logger.metadata([]) == :ok assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) =~ msg("[debug] hello") assert Logger.disable(self()) == :ok assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) == "" assert Logger.metadata([]) == :ok assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) == "" assert Logger.enable(self()) == :ok assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) =~ msg("[debug] hello") end test "compare_levels/2" do assert Logger.compare_levels(:debug, :debug) == :eq assert Logger.compare_levels(:debug, :info) == :lt assert Logger.compare_levels(:debug, :warn) == :lt assert Logger.compare_levels(:debug, :error) == :lt assert Logger.compare_levels(:info, :debug) == :gt assert Logger.compare_levels(:info, :info) == :eq assert Logger.compare_levels(:info, :warn) == :lt assert Logger.compare_levels(:info, :error) == :lt assert Logger.compare_levels(:warn, :debug) == :gt assert Logger.compare_levels(:warn, :info) == :gt assert Logger.compare_levels(:warn, :warn) == :eq assert Logger.compare_levels(:warn, :error) == :lt assert Logger.compare_levels(:error, :debug) == :gt assert Logger.compare_levels(:error, :info) == :gt assert Logger.compare_levels(:error, :warn) == :gt assert Logger.compare_levels(:error, :error) == :eq end test "debug/2" do assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) =~ msg("[debug] hello") assert capture_log(:info, fn -> assert Logger.debug("hello", []) == :ok end) == "" end test "info/2" do assert capture_log(fn -> assert Logger.info("hello", []) == :ok end) =~ msg("[info] hello") assert capture_log(:warn, fn -> assert Logger.info("hello", []) == :ok end) == "" end test "warn/2" do assert capture_log(fn -> assert Logger.warn("hello", []) == :ok end) =~ msg("[warn] hello") assert capture_log(:error, fn -> assert Logger.warn("hello", []) == :ok end) == "" end test "error/2" do assert capture_log(fn -> assert Logger.error("hello", []) == :ok end) =~ msg("[error] hello") end test "remove unused calls at compile time" do Logger.configure(compile_time_purge_level: :info) defmodule Sample do def debug do Logger.debug "hello" end def info do Logger.info "hello" end end assert capture_log(fn -> assert Sample.debug == :ok end) == "" assert capture_log(fn -> assert Sample.info == :ok end) =~ msg("[info] hello") after Logger.configure(compile_time_purge_level: :debug) end test "log/2 truncates messages" do Logger.configure(truncate: 4) assert capture_log(fn -> Logger.log(:debug, "hello") end) =~ "hell (truncated)" after Logger.configure(truncate: 8096) end test "log/2 with to_string/1 conversion" do Logger.configure(truncate: 4) assert capture_log(fn -> Logger.log(:debug, :hello) end) =~ "hell (truncated)" after Logger.configure(truncate: 8096) end test "log/2 does not fails when the Logger is off" do logger = Process.whereis(Logger) Process.unregister(Logger) try do assert Logger.log(:debug, "hello") == {:error, :noproc} after Process.register(logger, Logger) end end test "log/2 relies on sync_threshold" do Logger.remove_backend(:console) Logger.configure(sync_threshold: 0) for _ <- 1..1000, do: Logger.log(:info, "some message") after Logger.configure(sync_threshold: 20) Logger.add_backend(:console) end test "stop the application silently" do Application.put_env(:logger, :backends, []) Logger.App.stop() Application.start(:logger) assert capture_log(fn -> assert Logger.debug("hello", []) == :ok end) == "" assert {:ok, _} = Logger.add_backend(:console) assert Logger.add_backend(:console) == {:error, :already_present} after Application.put_env(:logger, :backends, [:console]) Logger.App.stop() Application.start(:logger) end test "restarts Logger.Config on Logger exits" do Process.whereis(Logger) |> Process.exit(:kill) wait_for_logger() wait_for_handler(Logger, Logger.Config) wait_for_handler(:error_logger, Logger.ErrorHandler) end test "Logger.Config updates config on config_change/3" do :ok = Logger.configure([level: :debug]) try do Application.put_env(:logger, :level, :error) assert Logger.App.config_change([level: :error], [], []) === :ok assert Logger.level() === :error after Logger.configure([level: :debug]) end end end elixir-lang-1.1.0~0.20150708/lib/logger/test/test_helper.exs000066400000000000000000000015661254730255300231700ustar00rootroot00000000000000Logger.configure_backend(:console, colors: [enabled: false]) ExUnit.start() defmodule Logger.Case do use ExUnit.CaseTemplate import ExUnit.CaptureIO using _ do quote do import Logger.Case end end def msg(msg) do ~r/\d\d\:\d\d\:\d\d\.\d\d\d #{Regex.escape(msg)}/ end def wait_for_handler(manager, handler) do unless handler in GenEvent.which_handlers(manager) do :timer.sleep(10) wait_for_handler(manager, handler) end end def wait_for_logger() do try do GenEvent.which_handlers(Logger) else _ -> :ok catch :exit, _ -> :timer.sleep(10) wait_for_logger() end end def capture_log(level \\ :debug, fun) do Logger.configure(level: level) capture_io(:user, fn -> fun.() Logger.flush() end) after Logger.configure(level: :debug) end end elixir-lang-1.1.0~0.20150708/lib/mix/000077500000000000000000000000001254730255300164605ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/000077500000000000000000000000001254730255300172265ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix.ex000066400000000000000000000150071254730255300203640ustar00rootroot00000000000000defmodule Mix do @moduledoc ~S""" Mix is a build tool that provides tasks for creating, compiling, testing Elixir projects, as well as handle dependencies, and more. ## Mix.Project The foundation of Mix is a project. A project can be defined by using `Mix.Project` in a module, usually placed in a file named `mix.exs`: defmodule MyApp.Mixfile do use Mix.Project def project do [app: :my_app, version: "1.0.0"] end end The `project/0` function is where the project information is defined and it allows developers to configure many tasks. After the project above is defined, there are many tasks one can run directly from the command line: * `mix compile` - compiles the current project * `mix test` - runs tests for the given project * `mix run` - runs a particular command inside the project Each task has its own options and sometimes specific configuration to be defined in the `project/0` function. You can use `mix help` to list all available tasks and `mix help NAME` to show help for a particular task. The best way to get started with your first project is by calling `mix new my_project` from the command line. ## Mix.Task Tasks are what make Mix extensible. Any project can extend Mix behaviour by adding their own tasks. For example, you can add the task below inside your project and it will be available to everyone that uses your project: defmodule Mix.Tasks.Hello do use Mix.Task def run(_) do Mix.shell.info "hello" end end Now they can invoke it with `mix hello`. ## Dependencies Another important feature in Mix is that it is able to manage your dependencies and integrates nicely with [the Hex package manager](http://hex.pm). In order to use dependencies, you just need to add a `:deps` key to your project configuration. We often extract the dependencies listing to its own functions: defmodule MyApp.Mixfile do use Mix.Project def project do [app: :my_app, version: "1.0.0", deps: deps] end defp deps do [{:ecto, "~> 0.2.5"}, {:plug, github: "elixir-lang/plug"}] end end You can run `mix help deps` to learn more about dependencies in Mix. ## Environments Mix provides environments. Environments allow developers to prepare and organize their project specifically for different scenarios. By default, Mix provides three environments: * `:dev` - the default environment * `:test` - the environment `mix test` runs on * `:prod` - the environment your dependencies runs on The environment can be changed via the command line by setting the `MIX_ENV` environment variable, for example: $ MIX_ENV=prod mix run server.exs ## Aliases Aliases are shortcuts or tasks specific to the current project. In the `Mix.Task` section, we have defined a task that would be available to everyone using our project as a dependency. What if we wanted the task to only be available for our project? Just define an alias: defmodule MyApp.Mixfile do use Mix.Project def project do [app: :my_app, version: "1.0.0", aliases: aliases] end defp aliases do [c: "compile", hello: &hello/1] end defp hello(_) do Mix.shell.info "Hello world" end end In the example above, we have defined two aliases. One is `mix c` which is a shortcut for `mix compile`. The other is named `mix hello`, which is the equivalent to the `Mix.Tasks.Hello` we have defined in the `Mix.Task` section. Aliases may also be lists, specifying multiple tasks to run at once: [all: [&hello/1, "deps.get --only #{Mix.env}", "compile"]] In the example above, we have defined an alias named `mix all`, that prints hello, then fetches dependencies specific to the current environment and compiles it. Arguments given to the alias will be appended to the arguments of the last task in the list, if the last task is a function they will be given as a list of strings to the function. Finally, aliases can also be use to augment existing tasks. Let's suppose you want to augment `mix clean` to clean another directory Mix does not know about: [clean: ["clean", &clean_extra/1]] Where `&clean_extra/1` would be a function in your `mix.exs` with extra clean up logic. Note aliases do not show up on `mix help`. """ use Application @doc false def start do {:ok, _} = Application.ensure_all_started(:mix) :ok end @doc false def start(_type, []) do import Supervisor.Spec children = [ worker(Mix.State, []), worker(Mix.TasksServer, []), worker(Mix.ProjectStack, []) ] opts = [strategy: :one_for_one, name: Mix.Supervisor, max_restarts: 0] Supervisor.start_link(children, opts) end @doc """ Returns the mix environment. """ def env do # env is not available on bootstrapping, so set a :dev default Mix.State.get(:env, :dev) end @doc """ Changes the current mix env. Be careful when invoking this function as any project configuration won't be reloaded. """ def env(env) when is_atom(env) do Mix.State.put(:env, env) end @doc """ Returns the default compilers used by Mix. It can be used in your `mix.exs` to prepend or append new compilers to Mix: def project do [compilers: Mix.compilers ++ [:foo, :bar]] end """ def compilers do [:yecc, :leex, :erlang, :elixir, :app] end @doc """ The shell is a wrapper for doing IO. It contains conveniences for asking the user information, printing status and so forth. It is also swappable, allowing developers to use a test shell that simply sends the messages to the current process. """ def shell do Mix.State.get(:shell, Mix.Shell.IO) end @doc """ Sets the current shell. """ def shell(shell) do Mix.State.put(:shell, shell) end @doc """ Raises a mix error that is nicely formatted. """ def raise(message) when is_binary(message) do Kernel.raise Mix.Error, mix: true, message: message end @doc """ Raises a mix compatible exception. A mix compatible exception has a `mix` field which mix uses to store the project or application name which is automatically by the formatting tools. """ def raise(exception, opts) when is_atom(exception) do Kernel.raise %{exception.exception(opts) | mix: true} end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/000077500000000000000000000000001254730255300200235ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/archive.ex000066400000000000000000000043441254730255300220070ustar00rootroot00000000000000defmodule Mix.Archive do @moduledoc """ Module responsible for managing [archives](http://www.erlang.org/doc/man/code.html). An archive is a zip file containing the app and beam files. A valid archive must be named with the name of the application and it should contain the relative paths beginning with the application name, e.g. the root of the zip file should be `my_app/ebin/Elixir.My.App.beam`. """ @doc """ Returns the archive name based on `app` and `version`. ## Examples iex> Mix.Archive.name("foo", nil) "foo.ez" iex> Mix.Archive.name("foo", "0.1.0") "foo-0.1.0.ez" """ def name(app, nil), do: "#{app}.ez" def name(app, vsn), do: "#{app}-#{vsn}.ez" @doc """ Returns the archive internal directory from its `path`. ## Examples iex> Mix.Archive.dir("foo/bar/baz-0.1.0.ez") "baz-0.1.0" """ def dir(path) do path |> Path.basename |> Path.rootname end @doc """ Returns the ebin directory inside the given archive path. ## Examples iex> Mix.Archive.ebin("foo/bar/baz-0.1.0.ez") "foo/bar/baz-0.1.0.ez/baz-0.1.0/ebin" """ def ebin(path) do dir = dir(path) Path.join [path, dir, "ebin"] end @doc """ Creates an application archive. It receives the archive file in the format `path/to/archive/app-vsn.ez` and the path to the root of the project to be archived. Everything in the `ebin` and `priv` directories is archived. Dependencies are not archived. """ def create(source, target) do source_path = Path.expand(source) target_path = Path.expand(target) dir = dir(target_path) |> String.to_char_list {:ok, _} = :zip.create(String.to_char_list(target_path), files_to_add(source_path, dir), uncompress: ['.beam', '.app']) :ok end defp files_to_add(path, dir) do File.cd! path, fn -> evsn = Path.wildcard(".elixir") ebin = Path.wildcard("ebin/*.{beam,app}") priv = Path.wildcard("priv/**/*") Enum.reduce evsn ++ ebin ++ priv, [], fn(f, acc) -> case File.read(f) do {:ok, bin} -> [{Path.join(dir, f) |> String.to_char_list, bin}|acc] {:error, _} -> acc end end end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/cli.ex000066400000000000000000000056741254730255300211440ustar00rootroot00000000000000defmodule Mix.CLI do @moduledoc false @doc """ Runs Mix according to the command line arguments. """ def main(args \\ System.argv) do Mix.Local.append_archives Mix.Local.append_paths # Make sure all messages the tests might have sent to the # Logger are printed before we shut down the VM. System.at_exit fn _ -> if Process.whereis(Logger), do: Logger.flush() end case check_for_shortcuts(args) do :help -> proceed(["help"]) :version -> display_version() nil -> proceed(args) end end defp proceed(args) do load_dot_config() load_mixfile() {task, args} = get_task(args) ensure_hex(task) change_env(task) run_task(task, args) end defp load_mixfile() do file = System.get_env("MIX_EXS") || "mix.exs" _ = if File.regular?(file) do Code.load_file(file) end end defp get_task(["-" <> _|_]) do Mix.shell.error "** (Mix) Cannot implicitly pass flags to default mix task, " <> "please invoke instead: mix #{Mix.Project.config[:default_task]}" exit({:shutdown, 1}) end defp get_task([h|t]) do {h, t} end defp get_task([]) do {Mix.Project.config[:default_task], []} end defp run_task(name, args) do try do Mix.Task.run "loadconfig" Mix.Task.run name, args rescue # We only rescue exceptions in the mix namespace, all # others pass through and will explode on the users face exception -> stacktrace = System.stacktrace if Map.get(exception, :mix) do mod = exception.__struct__ |> Module.split() |> Enum.at(0, "Mix") Mix.shell.error "** (#{mod}) #{Exception.message(exception)}" exit({:shutdown, 1}) else reraise exception, stacktrace end end end defp ensure_hex("local.hex"), do: :ok defp ensure_hex(_task), do: Mix.Tasks.Local.Hex.ensure_updated?() defp change_env(task) do if is_nil(System.get_env("MIX_ENV")) && (env = preferred_cli_env(task)) do Mix.env(env) if project = Mix.Project.pop do %{name: name, file: file} = project Mix.Project.push name, file end end end defp preferred_cli_env(task) do task = String.to_atom(task) Mix.Project.config[:preferred_cli_env][task] || default_cli_env(task) end defp default_cli_env(:test), do: :test defp default_cli_env(_), do: nil defp load_dot_config do path = Path.join(Mix.Utils.mix_home, "config.exs") if File.regular?(path) do Mix.Task.run "loadconfig", [path] end end defp display_version() do IO.puts "Mix #{System.version}" end # Check for --help or --version in the args defp check_for_shortcuts([first_arg|_]) when first_arg in ["--help", "-h", "-help"], do: :help defp check_for_shortcuts([first_arg|_]) when first_arg in ["--version", "-v"], do: :version defp check_for_shortcuts(_), do: nil end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/compilers/000077500000000000000000000000001254730255300220205ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/compilers/elixir.ex000066400000000000000000000166131254730255300236610ustar00rootroot00000000000000defmodule Mix.Compilers.Elixir do @moduledoc false @doc """ Compiles stale Elixir files. It expects a manifest file, the source directories, the extensions to read in sources, the destination directory, a flag to know if compilation is being forced or not and a callback to be invoked once (and only if) compilation starts. The manifest is written down with information including dependencies between modules, which helps it recompile only the modules that have changed at runtime. """ def compile(manifest, srcs, skip, exts, dest, force, on_start) do keep = srcs -- skip all = Mix.Utils.extract_files(keep, exts) {all_entries, skip_entries} = read_manifest(manifest, dest, keep) removed = for {_b, _m, source, _d, _f, _bin} <- all_entries, not(source in all), do: source changed = if force do # A config, path dependency or manifest has # changed, let's just compile everything all else modified = Mix.Utils.last_modified(manifest) all_mtimes = mtimes(all_entries) # Otherwise let's start with the new ones # plus the ones that have changed for(source <- all, not Enum.any?(all_entries, fn {_b, _m, s, _d, _f, _bin} -> s == source end), do: source) ++ for({_b, _m, source, _d, files, _bin} <- all_entries, times = Enum.map([source|files], &HashDict.fetch!(all_mtimes, &1)), Mix.Utils.stale?(times, [modified]), do: source) end {entries, changed} = remove_stale_entries(all_entries, removed ++ changed) stale = changed -- removed cond do stale != [] -> compile_manifest(manifest, entries ++ skip_entries, stale, dest, on_start) :ok removed != [] -> write_manifest(manifest, entries ++ skip_entries) :ok true -> :noop end end defp mtimes(entries) do Enum.reduce(entries, HashDict.new, fn {_b, _m, source, _d, files, _bin}, dict -> Enum.reduce([source|files], dict, fn file, dict -> if HashDict.has_key?(dict, file) do dict else HashDict.put(dict, file, Mix.Utils.last_modified(file)) end end) end) end @doc """ Removes compiled files. """ def clean(manifest) do case File.read(manifest) do {:ok, contents} -> contents |> String.split("\n") |> Enum.each &(&1 |> String.split("\t") |> hd |> File.rm) File.rm(manifest) {:error, _} -> :ok end end defp compile_manifest(manifest, entries, stale, dest, on_start) do Mix.Project.ensure_structure() true = Code.prepend_path(dest) on_start.() cwd = File.cwd! # Starts a server responsible for keeping track which files # were compiled and the dependencies between them. {:ok, pid} = Agent.start_link(fn -> entries end) try do _ = Kernel.ParallelCompiler.files :lists.usort(stale), each_module: &each_module(pid, dest, cwd, &1, &2, &3), each_file: &each_file(&1), dest: dest Agent.cast pid, fn entries -> write_manifest(manifest, entries) entries end after Agent.stop(pid, :infinity) end :ok end defp each_module(pid, dest, cwd, source, module, binary) do source = Path.relative_to(source, cwd) bin = Atom.to_string(module) beam = dest |> Path.join(bin <> ".beam") |> Path.relative_to(cwd) deps = Kernel.LexicalTracker.remotes(module) |> List.delete(module) |> :lists.usort |> Enum.map(&Atom.to_string(&1)) |> Enum.reject(&match?("elixir_" <> _, &1)) files = for file <- get_external_resources(module), File.regular?(file), relative = Path.relative_to(file, cwd), Path.type(relative) == :relative, do: relative Agent.cast pid, &:lists.keystore(beam, 1, &1, {beam, bin, source, deps, files, binary}) end defp get_external_resources(module) do for {:external_resource, values} <- module.__info__(:attributes), value <- values, do: value end defp each_file(file) do Mix.shell.info "Compiled #{file}" end ## Resolution # This function receives the manifest entries and some source # files that have changed. It then, recursively, figures out # all the files that changed (via the module dependencies) and # return their sources as the remaining entries. defp remove_stale_entries(all, []) do {all, []} end defp remove_stale_entries(all, changed) do remove_stale_entries(all, :lists.usort(changed), [], []) end defp remove_stale_entries([{beam, module, source, _d, _f, _bin} = entry|t], changed, removed, acc) do if source in changed do atom = String.to_atom(module) _ = File.rm(beam) _ = :code.purge(atom) _ = :code.delete(atom) remove_stale_entries(t, changed, [module|removed], acc) else remove_stale_entries(t, changed, removed, [entry|acc]) end end defp remove_stale_entries([], changed, removed, acc) do # If any of the dependencies for the remaining entries # were removed, get its source so we can remove them. next_changed = for {_b, _m, source, deps, _f, _bin} <- acc, Enum.any?(deps, &(&1 in removed)), do: source {acc, next} = remove_stale_entries(Enum.reverse(acc), next_changed) {acc, next ++ changed} end ## Manifest handling # Reads the manifest returning the results as tuples. # The beam files are read, removed and stored in memory. defp read_manifest(manifest, dest, keep_paths) do initial = {[], []} case File.read(manifest) do {:ok, contents} -> keep_paths = Enum.map(keep_paths, &(&1 <> "/")) Enum.reduce String.split(contents, "\n"), initial, fn x, acc -> read_manifest_entry(String.split(x, "\t"), acc, dest, keep_paths) end {:error, _} -> initial end end defp read_manifest_entry([_beam, module, source|deps], {keep, skip}, dest, keep_paths) do {deps, files} = case Enum.split_while(deps, &(&1 != "Elixir")) do {deps, ["Elixir"|files]} -> {deps, files} {deps, _} -> {deps, []} end # TODO: Notice we do not use beam from the file. # From Elixir v1.2 onwards, we can start writing "1" # instead of the beam file in write_manifest/2. entry = {Path.join(dest, module <> ".beam"), module, source, deps, files, nil} if String.starts_with?(source, keep_paths) do {[entry|keep], skip} else {keep, [entry|skip]} end end defp read_manifest_entry(_, acc, _dest, _skip_paths) do acc end # Writes the manifest separating entries by tabs. defp write_manifest(_manifest, []) do :ok end defp write_manifest(manifest, entries) do lines = Enum.map(entries, fn {beam, module, source, deps, files, binary} -> if binary, do: File.write!(beam, binary) tail = deps ++ ["Elixir"] ++ files [beam, module, source | tail] |> Enum.join("\t") end) # The Mix.Dep.Lock keeps all the project dependencies. Since Elixir # is a dependency itself, we need to touch the lock so the current # Elixir version, used to compile the files above, is properly stored. Mix.Dep.Lock.touch File.mkdir_p!(Path.dirname(manifest)) File.write!(manifest, Enum.join(lines, "\n")) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/compilers/erlang.ex000066400000000000000000000105251254730255300236310ustar00rootroot00000000000000defmodule Mix.Compilers.Erlang do @moduledoc false @doc """ Compiles the files in `src_dirs` with given extensions into the destination, automatically invoking the callback for each stale input and output pair (or for all if `force` is `true`) and removing files that no longer have a source, while keeping the manifest up to date. ## Examples For example, a simple compiler for Lisp Flavored Erlang would be implemented like: manifest = Path.join Mix.Project.manifest_path, ".compile.lfe" dest = Mix.Project.compile_path compile manifest, [{"src", dest}], :lfe, :beam, opts[:force], fn input, output -> :lfe_comp.file(to_erl_file(input), [output_dir: Path.dirname(output)]) end The command above will: 1. look for files ending with the `lfe` extension in `src` and their `beam` counterpart in `ebin` 2. for each stale file (or for all if `force` is `true`), invoke the callback passing the calculated input and output 3. update the manifest with the newly compiled outputs 4. remove any output in the manifest that does not have an equivalent source The callback must return `{:ok, mod}` or `:error` in case of error. An error is raised at the end if any of the files failed to compile. """ def compile(manifest, mappings, src_ext, dest_ext, force, callback) do files = for {src, dest} <- mappings do extract_targets(src, src_ext, dest, dest_ext, force) end |> Enum.concat compile(manifest, files, callback) end @doc """ Compiles the given src/dest tuples. A manifest file and a callback to be invoked for each src/dest pair must be given. A src/dest pair where destination is `nil` is considered to be up to date and won't be (re-)compiled. """ def compile(manifest, tuples, callback) do stale = for {:stale, src, dest} <- tuples, do: {src, dest} # Get the previous entries from the manifest entries = read_manifest(manifest) # Files to remove are the ones in the manifest # but they no longer have a source removed = Enum.filter(entries, fn entry -> not Enum.any?(tuples, fn {_status, _src, dest} -> dest == entry end) end) if stale == [] && removed == [] do :noop else Mix.Project.ensure_structure() # Let's prepend the newly created path so compiled files # can be accessed still during compilation (for behaviours # and what not). Code.prepend_path(Mix.Project.compile_path) # Remove manifest entries with no source Enum.each(removed, &File.rm/1) # Compile stale files and print the results results = for {input, output} <- stale do interpret_result(input, callback.(input, output)) end # Write final entries to manifest entries = (entries -- removed) ++ Enum.map(stale, &elem(&1, 1)) write_manifest(manifest, :lists.usort(entries)) # Raise if any error, return :ok otherwise if :error in results do Mix.raise "Encountered compilation errors." end :ok end end @doc """ Removes compiled files. """ def clean(manifest) do Enum.each read_manifest(manifest), &File.rm/1 File.rm manifest end @doc """ Converts the given file to a format accepted by the Erlang compilation tools. """ def to_erl_file(file) do to_char_list(file) end defp extract_targets(src_dir, src_ext, dest_dir, dest_ext, force) do files = Mix.Utils.extract_files(List.wrap(src_dir), List.wrap(src_ext)) for file <- files do module = module_from_artifact(file) target = Path.join(dest_dir, module <> "." <> to_string(dest_ext)) if force || Mix.Utils.stale?([file], [target]) do {:stale, file, target} else {:ok, file, target} end end end defp module_from_artifact(artifact) do artifact |> Path.basename |> Path.rootname end defp interpret_result(file, result) do case result do {:ok, _} -> Mix.shell.info "Compiled #{file}" :error -> nil end result end defp read_manifest(file) do case File.read(file) do {:ok, contents} -> String.split(contents, "\n") {:error, _} -> [] end end defp write_manifest(file, entries) do Path.dirname(file) |> File.mkdir_p! File.write!(file, Enum.join(entries, "\n")) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/config.ex000066400000000000000000000141161254730255300216310ustar00rootroot00000000000000defmodule Mix.Config do @moduledoc ~S""" Module for defining, reading and merging app configurations. Most commonly, this module is used to define your own configuration: use Mix.Config config :plug, key1: "value1", key2: "value2" import_config "#{Mix.env}.exs" All `config/*` macros, including `import_config/1`, are used to help define such configuration files. Furthermore, this module provides functions like `read!/1`, `merge/2` and friends which help manipulate configurations in general. Configuration set using `Mix.Config` will set the application env, so that `Application.get_env/3` and other `Application` functions can be used at run or compile time to retrieve or change the configuration. For example, the `:key1` value from application `:plug` (see above) can be retrieved with: "value1" = Application.fetch!(:plug, :key1) """ defmodule LoadError do defexception [:file, :error] def message(%LoadError{file: file, error: error}) do "could not load config #{Path.relative_to_cwd(file)}\n " <> "#{Exception.format_banner(:error, error)}" end end @doc false defmacro __using__(_) do quote do import Mix.Config, only: [config: 2, config: 3, import_config: 1] {:ok, agent} = Mix.Config.Agent.start_link var!(config_agent, Mix.Config) = agent end end @doc """ Configures the given application. Keyword lists are always deep merged. ## Examples The given `opts` are merged into the existing configuration for the given `app`. Conflicting keys are overridden by the ones specified in `opts`. For example, the declaration below: config :lager, log_level: :warn, mode: :truncate config :lager, log_level: :info, threshold: 1024 Will have a final configuration of: [log_level: :info, mode: :truncate, threshold: 1024] This final configuration can be retrieved at run or compile time: Application.get_all_env(:lager) """ defmacro config(app, opts) do quote do Mix.Config.Agent.merge var!(config_agent, Mix.Config), [{unquote(app), unquote(opts)}] end end @doc """ Configures the given key for the given application. Keyword lists are always deep merged. ## Examples The given `opts` are merged into the existing values for `key` in the given `app`. Conflicting keys are overridden by the ones specified in `opts`. For example, the declaration below: config :ecto, Repo, log_level: :warn config :ecto, Repo, log_level: :info, pool_size: 10 Will have a final value for `Repo` of: [log_level: :info, pool_size: 10] This final value can be retrieved at run or compile time: Application.get_env(:ecto, Repo) """ defmacro config(app, key, opts) do quote do Mix.Config.Agent.merge var!(config_agent, Mix.Config), [{unquote(app), [{unquote(key), unquote(opts)}]}] end end @doc ~S""" Imports configuration from the given file. The path is expected to be relative to the directory the current configuration file is on. ## Examples This is often used to emulate configuration across environments: import_config "#{Mix.env}.exs" Or to import files from children in umbrella projects: import_config "../apps/*/config/config.exs" """ defmacro import_config(file) do quote do Mix.Config.Agent.merge( var!(config_agent, Mix.Config), Mix.Config.read_wildcard!(Path.expand(unquote(file), __DIR__)) ) end end @doc """ Reads and validates a configuration file. """ def read!(file) do try do {config, binding} = Code.eval_file(file) config = case List.keyfind(binding, {:config_agent, Mix.Config}, 0) do {_, agent} -> get_config_and_stop_agent(agent) nil -> config end validate!(config) config rescue e in [LoadError] -> reraise(e, System.stacktrace) e -> reraise(LoadError, [file: file, error: e], System.stacktrace) end end defp get_config_and_stop_agent(agent) do config = Mix.Config.Agent.get(agent) Mix.Config.Agent.stop(agent) config end @doc """ Reads many configuration files given by wildcard into a single config. Raises an error if `path` is a concrete filename (with no wildcards) but the corresponding file does not exist. """ def read_wildcard!(path) do paths = if String.contains?(path, ~w(* ? [ {))do Path.wildcard(path) else [path] end Enum.reduce(paths, [], &merge(&2, read!(&1))) end @doc """ Persists the given configuration by modifying the configured applications environment. """ def persist(config) do for {app, kw} <- config, {k, v} <- kw do :application.set_env(app, k, v, persistent: true) end :ok end @doc """ Validates a configuration. """ def validate!(config) do if is_list(config) do Enum.all?(config, fn {app, value} when is_atom(app) -> if Keyword.keyword?(value) do true else raise ArgumentError, "expected config for app #{inspect app} to return keyword list, got: #{inspect value}" end _ -> false end) else raise ArgumentError, "expected config file to return keyword list, got: #{inspect config}" end end @doc """ Merges two configurations. The configuration of each application is merged together with the values in the second one having higher preference than the first in case of conflicts. ## Examples iex> Mix.Config.merge([app: [k: :v1]], [app: [k: :v2]]) [app: [k: :v2]] iex> Mix.Config.merge([app1: []], [app2: []]) [app1: [], app2: []] """ def merge(config1, config2) do Keyword.merge(config1, config2, fn _, app1, app2 -> Keyword.merge(app1, app2, &deep_merge/3) end) end defp deep_merge(_key, value1, value2) do if Keyword.keyword?(value1) and Keyword.keyword?(value2) do Keyword.merge(value1, value2, &deep_merge/3) else value2 end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/config/000077500000000000000000000000001254730255300212705ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/config/agent.ex000066400000000000000000000007311254730255300227250ustar00rootroot00000000000000defmodule Mix.Config.Agent do @moduledoc false @typep config :: Keyword.t @spec start_link() :: {:ok, pid} def start_link do Agent.start_link fn -> [] end end @spec stop(pid) :: :ok def stop(agent) do Agent.stop(agent) end @spec get(pid) :: config def get(agent) do Agent.get(agent, &(&1)) end @spec merge(pid, config) :: config def merge(agent, new_config) do Agent.update(agent, &Mix.Config.merge(&1, new_config)) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep.ex000066400000000000000000000254661254730255300211460ustar00rootroot00000000000000defmodule Mix.Dep do @moduledoc false @doc """ The Mix.Dep a struct keeps information about your project dependencies. It contains: * `scm` - a module representing the source code management tool (SCM) operations * `app` - the application name as an atom * `requirement` - a binary or regex with the dependency's requirement * `status` - the current status of the dependency, check `Mix.Dep.format_status/1` for more info * `opts` - the options given by the developer * `deps` - dependencies of this dependency * `top_level` - true if dependency was defined in the top-level project * `manager` - the project management, possible values: `:rebar` | `:mix` | `:make` | `nil` * `from` - path to the file where the dependency was defined * `extra` - a slot for adding extra configuration based on the manager; the information on this field is private to the manager and should not be relied on A dependency is in two specific states: loaded and unloaded. When a dependency is unloaded, it means Mix only parsed its specification and made no attempt to actually load the dependency or validate its status. When the dependency is loaded, it means Mix attempted to fetch, load and validate it, the status is set in the status field. Furthermore, in the `opts` fields, Mix keeps some internal options, which can be accessed by SCMs: * `:app` - the application name * `:dest` - the destination path for the dependency * `:lock` - the lock information retrieved from mix.lock * `:build` - the build path for the dependency """ defstruct scm: nil, app: nil, requirement: nil, status: nil, opts: [], deps: [], top_level: false, extra: [], manager: nil, from: nil @type t :: %__MODULE__{ scm: module, app: atom, requirement: String.t | Regex.t, status: atom, opts: Keyword.t, top_level: boolean, manager: :rebar | :mix | :make | nil, from: String.t, extra: term} @doc """ Returns all children dependencies for the current project, as well as the defined apps in case of umbrella projects. The children dependencies returned by this function were not loaded yet. ## Exceptions This function raises an exception if any of the dependencies provided in the project are in the wrong format. """ defdelegate children(otps), to: Mix.Dep.Loader @doc """ Returns loaded dependencies recursively as a `Mix.Dep` struct. ## Exceptions This function raises an exception if any of the dependencies provided in the project are in the wrong format. """ def loaded(opts) do Mix.Dep.Converger.converge(nil, nil, opts, &{&1, &2, &3}) |> elem(0) end @doc """ Receives a list of dependency names and returns loaded `Mix.Dep`s. Logs a message if the dependency could not be found. ## Exceptions This function raises an exception if any of the dependencies provided in the project are in the wrong format. """ def loaded_by_name(given, all_deps \\ nil, opts) do all_deps = all_deps || loaded(opts) # Ensure all apps are atoms apps = to_app_names(given) # We need to keep the order of deps, loaded/1 properly orders them deps = Enum.filter(all_deps, &(&1.app in apps)) Enum.each apps, fn(app) -> unless Enum.any?(all_deps, &(&1.app == app)) do Mix.raise "Unknown dependency #{app} for environment #{Mix.env}" end end deps end @doc """ Runs the given `fun` inside the given dependency project by changing the current working directory and loading the given project onto the project stack. It is expected a loaded dependency as argument. """ def in_dependency(dep, post_config \\ [], fun) def in_dependency(%Mix.Dep{app: app, opts: opts}, config, fun) do # Set the app_path to be the one stored in the dependency. # This is important because the name of application in the # mix.exs file can be different than the actual name and we # choose to respect the one in the mix.exs config = Keyword.merge(Mix.Project.deps_config, config) config = Keyword.put(config, :app_path, opts[:build]) env = opts[:env] || :prod old_env = Mix.env try do Mix.env(env) Mix.Project.in_project(app, opts[:dest], config, fun) after Mix.env(old_env) end end @doc """ Formats the status of a dependency. """ def format_status(%Mix.Dep{status: {:ok, _vsn}}), do: "ok" def format_status(%Mix.Dep{status: {:noappfile, path}}), do: "could not find an app file at #{Path.relative_to_cwd(path)}. " <> "This may happen if the dependency was not yet compiled, " <> "or you specified the wrong application name in your deps, " <> "or the dependency indeed has no app file (then you can pass app: false as option)" def format_status(%Mix.Dep{status: {:invalidapp, path}}), do: "the app file at #{Path.relative_to_cwd(path)} is invalid" def format_status(%Mix.Dep{status: {:invalidvsn, vsn}}), do: "the app file contains an invalid version: #{inspect vsn}" def format_status(%Mix.Dep{status: {:nomatchvsn, vsn}, requirement: req}), do: "the dependency does not match the requirement #{inspect req}, got #{inspect vsn}" def format_status(%Mix.Dep{status: {:lockmismatch, _}}), do: "lock mismatch: the dependency is out of date (run `mix deps.get` to fetch locked version)" def format_status(%Mix.Dep{status: :lockoutdated}), do: "lock outdated: the lock is outdated compared to the options in your mixfile" def format_status(%Mix.Dep{status: :nolock}), do: "the dependency is not locked" def format_status(%Mix.Dep{status: :compile}), do: "the dependency build is outdated, please run `#{mix_env_var}mix deps.compile`" def format_status(%Mix.Dep{app: app, status: {:divergedreq, other}} = dep) do "the dependency #{app} defined\n" <> "#{dep_status(dep)}" <> "\n does not match the requirement specified\n" <> "#{dep_status(other)}" <> "\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`" end def format_status(%Mix.Dep{app: app, status: {:diverged, other}} = dep) do "different specs were given for the #{app} app:\n" <> "#{dep_status(dep)}#{dep_status(other)}" <> "\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`" end def format_status(%Mix.Dep{app: app, status: {:overridden, other}} = dep) do "the dependency #{app} in #{Path.relative_to_cwd(dep.from)} is overriding a child dependency:\n" <> "#{dep_status(dep)}#{dep_status(other)}" <> "\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`" end def format_status(%Mix.Dep{status: {:unavailable, _}, scm: scm}) do if scm.fetchable? do "the dependency is not available, run `mix deps.get`" else "the dependency is not available" end end def format_status(%Mix.Dep{status: {:elixirlock, _}}), do: "the dependency is built with an out-of-date elixir version, run `#{mix_env_var}mix deps.compile`" defp dep_status(%Mix.Dep{app: app, requirement: req, opts: opts, from: from}) do info = {app, req, Dict.drop(opts, [:dest, :lock, :env, :build])} "\n > In #{Path.relative_to_cwd(from)}:\n #{inspect info}\n" end @doc """ Checks the lock for the given dependency and update its status accordingly. """ def check_lock(%Mix.Dep{scm: scm, app: app, opts: opts} = dep, lock) do if rev = lock[app] do opts = Keyword.put(opts, :lock, rev) end if available?(dep) do case scm.lock_status(opts) do :mismatch -> status = if rev, do: {:lockmismatch, rev}, else: :nolock %{dep | status: status, opts: opts} :outdated -> # Don't include the lock in the dependency if it is outdated %{dep | status: :lockoutdated} :ok -> if vsn = old_elixir_lock(dep) do %{dep | status: {:elixirlock, vsn}, opts: opts} else %{dep | opts: opts} end end else %{dep | opts: opts} end end @doc """ Returns `true` if the dependency is ok. """ def ok?(%Mix.Dep{status: {:ok, _}}), do: true def ok?(%Mix.Dep{}), do: false @doc """ Checks if a dependency is available. Available dependencies are the ones that can be loaded. """ def available?(%Mix.Dep{status: {:overridden, _}}), do: false def available?(%Mix.Dep{status: {:diverged, _}}), do: false def available?(%Mix.Dep{status: {:divergedreq, _}}), do: false def available?(%Mix.Dep{status: {:unavailable, _}}), do: false def available?(%Mix.Dep{}), do: true @doc """ Formats a dependency for printing. """ def format_dep(%Mix.Dep{scm: scm, app: app, status: status, opts: opts}) do version = case status do {:ok, vsn} when vsn != nil -> "#{vsn} " _ -> "" end "#{app} #{version}(#{scm.format(opts)})" end @doc """ Returns all load paths for the given dependency. Automatically derived from source paths. """ def load_paths(%Mix.Dep{opts: opts} = dep) do build_path = Path.dirname(opts[:build]) Enum.map source_paths(dep), fn path -> Path.join [build_path, Path.basename(path), "ebin"] end end @doc """ Returns all source paths. Source paths are the directories that contains ebin files for a given dependency. All managers, except rebar, have only one source path. """ def source_paths(%Mix.Dep{manager: :rebar, opts: opts, extra: extra}) do # Add root dir and all sub dirs with ebin/ directory sub_dirs = Enum.map(extra[:sub_dirs] || [], fn path -> Path.join(opts[:dest], path) end) [opts[:dest] | sub_dirs] |> Enum.map(&Path.wildcard(&1)) |> Enum.concat |> Enum.filter(fn p -> p |> Path.join("ebin") |> File.dir? end) end def source_paths(%Mix.Dep{opts: opts}) do [opts[:dest]] end @doc """ Return `true` if dependency is a mix project. """ def mix?(%Mix.Dep{manager: manager}) do manager == :mix end @doc """ Return `true` if dependency is a rebar project. """ def rebar?(%Mix.Dep{manager: manager}) do manager == :rebar end @doc """ Return `true` if dependency is a make project. """ def make?(%Mix.Dep{manager: manager}) do manager == :make end ## Helpers defp mix_env_var do if Mix.env == :dev do "" else "MIX_ENV=#{Mix.env} " end end defp to_app_names(given) do Enum.map given, fn(app) -> if is_binary(app), do: String.to_atom(app), else: app end end defp old_elixir_lock(%Mix.Dep{opts: opts}) do old_vsn = Mix.Dep.Lock.elixir_vsn(opts[:build]) if old_vsn && old_vsn != System.version do old_vsn end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/000077500000000000000000000000001254730255300205735ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/converger.ex000066400000000000000000000165551254730255300231370ustar00rootroot00000000000000# This module is the one responsible for converging # dependencies in a recursive fashion. This # module and its functions are private to Mix. defmodule Mix.Dep.Converger do @moduledoc false @doc """ Topsorts the given dependencies. """ def topsort(deps) do graph = :digraph.new try do Enum.each(deps, fn %Mix.Dep{app: app} -> :digraph.add_vertex(graph, app) end) Enum.each(deps, fn %Mix.Dep{app: app, deps: other_deps} -> Enum.each(other_deps, fn %Mix.Dep{app: other_app} -> :digraph.add_edge(graph, other_app, app) end) end) if apps = :digraph_utils.topsort(graph) do Enum.map(apps, fn(app) -> Enum.find(deps, fn(%Mix.Dep{app: other_app}) -> app == other_app end) end) else Mix.raise "Could not sort dependencies. There are cycles in the dependency graph." end after :digraph.delete(graph) end end @doc """ Converges all dependencies from the current project, including nested dependencies. There is a callback that is invoked for each dependency and must return an updated dependency in case some processing is done. See `Mix.Dep.Loader.children/1` for options. """ def converge(acc, lock, opts, callback) do {deps, acc, lock} = all(acc, lock, opts, callback) {topsort(deps), acc, lock} end defp all(acc, lock, opts, callback) do main = Mix.Dep.Loader.children(opts) main = Enum.map(main, &(%{&1 | top_level: true})) apps = Enum.map(main, &(&1.app)) # Run converger for all dependencies, except remote # dependencies. Since the remote converger may be # lazily loaded, we need to check for it on every # iteration. {deps, rest, lock} = all(main, [], [], apps, callback, acc, lock, fn dep -> if (converger = Mix.RemoteConverger.get) && converger.remote?(dep) do {:loaded, dep} else {:unloaded, dep, nil} end end) # Run remote converger if one is available and rerun mix's # converger with the new information if converger = Mix.RemoteConverger.get do # If there is a lock, it means we are doing a get/update # and we need to hit the remote converger which do external # requests and what not. In case of deps.check, deps and so # on, there is no lock, so we won't hit this branch. if lock do lock = converger.converge(deps, lock) end deps = deps |> Enum.reject(&converger.remote?(&1)) |> Enum.into(HashDict.new, &{&1.app, &1}) # In case there is no lock, we will read the current lock # which is potentially stale. So converger.deps/2 needs to # always check if the data it finds in the lock is actually # valid. lock_for_converger = lock || Mix.Dep.Lock.read all(main, [], [], apps, callback, rest, lock, fn dep -> cond do cached = deps[dep.app] -> {:loaded, cached} true -> {:unloaded, dep, converger.deps(dep, lock_for_converger)} end end) else {deps, rest, lock} end end # We traverse the tree of dependencies in a breadth- # first fashion. The reason for this is that we converge # dependencies, but allow the parent to override any # dependency in the child. Consider this tree with # dependencies `a`, `b`, etc and the order they are # converged: # # * project # 1) a # 2) b # 4) d # 3) c # 5) e # 6) f # 7) d # # Notice that the `d` dependency exists as a child of `b` # and child of `f`. In case the dependency is the same, # we proceed. However, if there is a conflict, for instance # different git repositories is used as source in each, we # raise an exception. # # In order to solve such dependencies, we allow the project # to specify the same dependency, but it will be considered # to have higher priority: # # * project # 1) a # 2) b # 5) d # 3) c # 6) e # 7) f # 8) d # 4) d # # Now, since `d` was specified in a parent project, no # exception is going to be raised since d is considered # to be the authoritative source. defp all([dep|t], acc, upper_breadths, current_breadths, callback, rest, lock, cache) do cond do new_acc = diverged_deps(acc, upper_breadths, dep) -> all(t, new_acc, upper_breadths, current_breadths, callback, rest, lock, cache) true -> dep = case cache.(dep) do {:loaded, cached_dep} -> cached_dep {:unloaded, dep, children} -> {dep, rest, lock} = callback.(dep, rest, lock) # After we invoke the callback (which may actually check out the # dependency), we load the dependency including its latest info # and children information. Mix.Dep.Loader.load(dep, children) end dep = %{dep | deps: reject_non_fullfilled_optional(dep.deps, current_breadths)} {acc, rest, lock} = all(t, [dep|acc], upper_breadths, current_breadths, callback, rest, lock, cache) all(dep.deps, acc, current_breadths, Enum.map(dep.deps, &(&1.app)) ++ current_breadths, callback, rest, lock, cache) end end defp all([], acc, _upper, _current, _callback, rest, lock, _cache) do {acc, rest, lock} end # Look for divergence in dependencies. # # If the same dependency is specified more than once, # we need to guarantee they converge. If they don't # converge, we mark them as diverged. # # The only exception is when the dependency that # diverges is in the upper breadth, in those cases we # also check for the override option and mark the dependency # as overridden instead of diverged. defp diverged_deps(list, upper_breadths, dep) do %Mix.Dep{app: app} = dep in_upper? = app in upper_breadths {acc, match} = Enum.map_reduce list, false, fn(other, match) -> %Mix.Dep{app: other_app, opts: other_opts} = other cond do app != other_app -> {other, match} in_upper? && other_opts[:override] -> {other, true} converge?(other, dep) -> {with_matching_req(other, dep), true} true -> tag = if in_upper?, do: :overridden, else: :diverged {%{other | status: {tag, dep}}, true} end end if match, do: acc end defp converge?(%Mix.Dep{scm: scm1, opts: opts1}, %Mix.Dep{scm: scm2, opts: opts2}) do scm1 == scm2 and mix_equal?(opts1, opts2) and scm1.equal?(opts1, opts2) end defp mix_equal?(opts1, opts2) do Keyword.fetch(opts1, :app) == Keyword.fetch(opts2, :app) and Keyword.fetch(opts1, :env) == Keyword.fetch(opts2, :env) and Keyword.fetch(opts1, :compile) == Keyword.fetch(opts2, :compile) end defp reject_non_fullfilled_optional(children, upper_breadths) do Enum.reject children, fn %Mix.Dep{app: app, opts: opts} -> opts[:optional] && not(app in upper_breadths) end end defp with_matching_req(%Mix.Dep{} = other, %Mix.Dep{} = dep) do case other.status do {:ok, vsn} when not is_nil(vsn) -> if Mix.Dep.Loader.vsn_match?(dep.requirement, vsn, dep.app) do other else %{other | status: {:divergedreq, dep}} end _ -> other end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/fetcher.ex000066400000000000000000000111021254730255300225440ustar00rootroot00000000000000# Module responsible for fetching (getting/updating) # dependencies from their sources. # # The new_lock and old_lock mechanism exists to signal # externally which dependencies need to be updated and # which ones do not. defmodule Mix.Dep.Fetcher do @moduledoc false import Mix.Dep, only: [format_dep: 1, check_lock: 2, available?: 1, ok?: 1] @doc """ Fetches all dependencies. """ def all(old_lock, new_lock, opts) do result = Mix.Dep.Converger.converge([], new_lock, opts, &do_fetch/3) {apps, _deps} = do_finalize(result, old_lock, opts) apps end @doc """ Fetches the dependencies with the given names and their children recursively. """ def by_name(names, old_lock, new_lock, opts) do fetcher = fetch_by_name(names, new_lock) result = Mix.Dep.Converger.converge([], new_lock, opts, fetcher) {apps, deps} = do_finalize(result, old_lock, opts) # Check if all given dependencies are loaded or fail _ = Mix.Dep.loaded_by_name(names, deps, opts) apps end defp fetch_by_name(given, lock) do names = to_app_names(given) fn(%Mix.Dep{app: app} = dep, acc, new_lock) -> # Only fetch if dependency is in given names or if lock has # been changed for dependency by remote converger if app in names or lock[app] != new_lock[app] do do_fetch(dep, acc, new_lock) else {dep, acc, new_lock} end end end defp do_fetch(dep, acc, lock) do %Mix.Dep{app: app, scm: scm, opts: opts} = dep = check_lock(dep, lock) cond do # Dependencies that cannot be fetched are always compiled afterwards not scm.fetchable? -> {dep, [app|acc], lock} # If the dependency is not available or we have a lock mismatch out_of_date?(dep) -> new = if scm.checked_out?(opts) do Mix.shell.info "* Updating #{format_dep(dep)}" scm.update(opts) else Mix.shell.info "* Getting #{format_dep(dep)}" scm.checkout(opts) end if new do {dep, [app|acc], Map.put(lock, app, new)} else {dep, acc, lock} end # The dependency is ok or has some other error true -> {dep, acc, lock} end end defp out_of_date?(%Mix.Dep{status: {:lockmismatch, _}}), do: true defp out_of_date?(%Mix.Dep{status: :lockoutdated}), do: true defp out_of_date?(%Mix.Dep{status: :nolock}), do: true defp out_of_date?(%Mix.Dep{status: {:unavailable, _}}), do: true defp out_of_date?(%Mix.Dep{}), do: false defp do_finalize({all_deps, apps, new_lock}, old_lock, opts) do # Let's get the loaded versions of deps deps = Mix.Dep.loaded_by_name(apps, all_deps, opts) # Note we only retrieve the parent dependencies of the updated # deps if all dependencies are available. This is because if a # dependency is missing, it could directly affect one of the # dependencies we are trying to compile, causing the whole thing # to fail. # # If there is any other dependency that is not ok, we include # it for compilation too, this is our best to try to solve the # maximum we can at each deps.get and deps.update. if Enum.all?(all_deps, &available?/1) do deps = (with_depending(deps, all_deps) ++ Enum.filter(all_deps, fn dep -> not ok?(dep) end)) |> Enum.uniq(&(&1.app)) end # Merge the new lock on top of the old to guarantee we don't # leave out things that could not be fetched and save it. lock = Dict.merge(old_lock, new_lock) Mix.Dep.Lock.write(lock) mark_as_fetched(deps) {apps, all_deps} end defp mark_as_fetched(deps) do # If the dependency is fetchable, we are going to write a .fetch # file to it. Each build, regardless of the environment and location, # will compared against this .fetch file to know if the dependency # needs recompiling. _ = for %Mix.Dep{scm: scm, opts: opts} <- deps, scm.fetchable? do File.touch! Path.join opts[:dest], ".fetch" end :ok end defp with_depending(deps, all_deps) do deps ++ do_with_depending(deps, all_deps) end defp do_with_depending([], _all_deps) do [] end defp do_with_depending(deps, all_deps) do dep_names = Enum.map(deps, fn dep -> dep.app end) parents = Enum.filter all_deps, fn dep -> Enum.any?(dep.deps, &(&1.app in dep_names)) end do_with_depending(parents, all_deps) ++ parents end defp to_app_names(given) do Enum.map(given, fn(app) -> if is_binary(app), do: String.to_atom(app), else: app end) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/loader.ex000066400000000000000000000171561254730255300224110ustar00rootroot00000000000000# This module is responsible for loading dependencies # of the current project. This module and its functions # are private to Mix. defmodule Mix.Dep.Loader do @moduledoc false @doc """ Gets all direct children of the current `Mix.Project` as a `Mix.Dep` struct. Umbrella project dependencies are included as children. By default, it will filter all dependencies that does not match current environment, behaviour can be overridden via options. ## Options * `:env` - filter dependencies on given environments """ def children(opts) do mix_children(opts) ++ Mix.Dep.Umbrella.unloaded end @doc """ Loads the given dependency information, including its latest status and children. """ def load(dep, children) do %Mix.Dep{manager: manager, scm: scm, opts: opts} = dep dep = %{dep | status: scm_status(scm, opts)} dest = opts[:dest] {dep, children} = cond do not ok?(dep.status) -> {dep, []} mix?(dest) -> mix_dep(dep, children) # If not an explicit rebar or mix dependency # but came from rebar, assume to be a rebar dep. rebar?(dest) or manager == :rebar -> rebar_dep(dep, children) make?(dest) -> make_dep(dep) true -> {dep, []} end %{validate_app(dep) | deps: children} end @doc """ Checks if a requirement from a dependency matches the given version. """ def vsn_match?(nil, _actual, _app), do: true def vsn_match?(req, actual, app) do if Regex.regex?(req) do actual =~ req else case Version.parse(actual) do {:ok, version} -> case Version.parse_requirement(req) do {:ok, req} -> Version.match?(version, req) :error -> Mix.raise "Invalid requirement #{req} for app #{app}" end :error -> Mix.raise "The application #{app} specified a non Semantic Version #{actual}. " <> "Mix can only match the requirement #{req} against Semantic Versions, to match against any " <> "version, please use a regex as requirement" end end end ## Helpers def to_dep(tuple, from, manager \\ nil) do %{with_scm_and_app(tuple) | from: from, manager: manager} end defp with_scm_and_app({app, opts}) when is_list(opts) do with_scm_and_app({app, nil, opts}) end defp with_scm_and_app({app, req}) do with_scm_and_app({app, req, []}) end defp with_scm_and_app({app, req, opts} = other) when is_atom(app) and is_list(opts) do unless is_binary(req) or Regex.regex?(req) or is_nil(req) do invalid_dep_format(other) end unless Keyword.keyword?(opts) do invalid_dep_format(other) end bin_app = Atom.to_string(app) dest = Path.join(Mix.Project.deps_path, bin_app) build = Path.join([Mix.Project.build_path, "lib", bin_app]) opts = opts |> Keyword.put(:dest, dest) |> Keyword.put(:build, build) {scm, opts} = get_scm(app, opts) if !scm && Mix.Tasks.Local.Hex.ensure_installed?(app) do _ = Mix.Tasks.Local.Hex.start() {scm, opts} = get_scm(app, opts) end unless scm do Mix.raise "Could not find a SCM for dependency #{inspect app} from #{inspect Mix.Project.get}" end %Mix.Dep{ scm: scm, app: app, requirement: req, status: scm_status(scm, opts), opts: opts} end defp with_scm_and_app(other) do invalid_dep_format(other) end defp get_scm(app, opts) do Enum.find_value Mix.SCM.available, {nil, opts}, fn(scm) -> (new = scm.accepts_options(app, opts)) && {scm, new} end end defp scm_status(scm, opts) do if scm.checked_out?(opts) do {:ok, nil} else {:unavailable, opts[:dest]} end end defp ok?({:ok, _}), do: true defp ok?(_), do: false defp mix?(dest) do any_of?(dest, ["mix.exs"]) end defp rebar?(dest) do any_of?(dest, ["rebar", "rebar.config", "rebar.config.script"]) end defp make?(dest) do any_of?(dest, ["Makefile", "Makefile.win"]) end defp any_of?(dest, files) do Enum.any?(files, &File.regular?(Path.join(dest, &1))) end defp invalid_dep_format(dep) do Mix.raise """ Dependency specified in the wrong format: #{inspect dep} Expected: {app, opts} | {app, requirement} | {app, requirement, opts} Where: app :: atom requirement :: String.t | Regex.t opts :: Keyword.t """ end ## Fetching defp mix_dep(%Mix.Dep{opts: opts} = dep, nil) do Mix.Dep.in_dependency(dep, fn _ -> if Mix.Project.umbrella? do opts = Keyword.put_new(opts, :app, false) end deps = mix_children(env: opts[:env] || :prod) ++ Mix.Dep.Umbrella.unloaded {%{dep | manager: :mix, opts: opts}, deps} end) end # If we have a Mix dependency that came from a remote converger, # we just use the dependencies given by the remote converger, # we don't need to load the mixfile at all. We can only do this # because umbrella projects are not supported in remotes. defp mix_dep(%Mix.Dep{opts: opts} = dep, children) do from = Path.join(opts[:dest], "mix.exs") deps = Enum.map(children, &to_dep(&1, from)) {%{dep | manager: :mix}, deps} end defp rebar_dep(%Mix.Dep{} = dep, children) do Mix.Dep.in_dependency(dep, fn _ -> rebar = Mix.Rebar.load_config(".") extra = Dict.take(rebar, [:sub_dirs]) deps = if children do from = Path.absname("rebar.config") Enum.map(children, &to_dep(&1, from, :rebar)) else rebar_children(rebar) end {%{dep | manager: :rebar, extra: extra}, deps} end) end defp make_dep(dep) do {%{dep | manager: :make}, []} end defp mix_children(opts) do from = Path.absname("mix.exs") deps = Enum.map(Mix.Project.config[:deps] || [], &to_dep(&1, from)) # Filter deps not matching mix environment if env = opts[:env] do Enum.filter(deps, fn %Mix.Dep{opts: opts} -> only = opts[:only] if only, do: env in List.wrap(only), else: true end) else deps end end defp rebar_children(root_config) do from = Path.absname("rebar.config") Mix.Rebar.recur(root_config, fn config -> Mix.Rebar.deps(config) |> Enum.map(&to_dep(&1, from, :rebar)) end) |> Enum.concat end defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app, status: status} = dep) do opts_app = opts[:app] cond do not ok?(status) -> dep recently_fetched?(dep) -> %{dep | status: :compile} opts_app == false -> dep true -> path = if is_binary(opts_app), do: opts_app, else: "ebin/#{app}.app" path = Path.expand(path, opts[:build]) %{dep | status: app_status(path, app, req)} end end defp recently_fetched?(%Mix.Dep{opts: opts, scm: scm}) do scm.fetchable? && Mix.Utils.stale?([Path.join(opts[:dest], ".fetch")], [Path.join(opts[:build], ".compile.fetch")]) end defp app_status(app_path, app, req) do case :file.consult(app_path) do {:ok, [{:application, ^app, config}]} -> case List.keyfind(config, :vsn, 0) do {:vsn, actual} when is_list(actual) -> actual = IO.iodata_to_binary(actual) if vsn_match?(req, actual, app) do {:ok, actual} else {:nomatchvsn, actual} end {:vsn, actual} -> {:invalidvsn, actual} nil -> {:invalidvsn, nil} end {:ok, _} -> {:invalidapp, app_path} {:error, _} -> {:noappfile, app_path} end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/lock.ex000066400000000000000000000046271254730255300220720ustar00rootroot00000000000000# This module keeps a lock file and the manifest for the lock file. # The lockfile keeps the latest dependency information while the # manifest is used whenever a dependency is affected via any of the # deps.* tasks. We also keep the Elixir version in the manifest file. defmodule Mix.Dep.Lock do @moduledoc false @manifest ".compile.lock" @doc """ Returns the manifest file for dependencies. """ @spec manifest(Path.t) :: Path.t def manifest(manifest_path \\ Mix.Project.manifest_path) do Path.join(manifest_path, @manifest) end @doc """ Touches the manifest timestamp unless it is an umbrella application. """ @spec touch() :: :ok def touch() do _ = unless Mix.Project.umbrella?, do: touch(Mix.Project.manifest_path) :ok end @doc """ Touches the manifest timestamp and updates the elixir version. """ @spec touch(Path.t) :: :ok def touch(manifest_path) do File.mkdir_p!(manifest_path) File.write!(Path.join(manifest_path, @manifest), System.version) end @doc """ Returns the elixir version in the lock manifest. """ @spec elixir_vsn() :: binary | nil def elixir_vsn() do elixir_vsn(Mix.Project.manifest_path) end @doc """ Returns the elixir version in the lock manifest in the given path. """ @spec elixir_vsn(Path.t) :: binary | nil def elixir_vsn(manifest_path) do case File.read(manifest(manifest_path)) do {:ok, contents} -> contents {:error, _} -> nil end end @doc """ Read the lockfile, returns a map containing each app name and its current lock information. """ @spec read() :: map def read() do case File.read(lockfile) do {:ok, info} -> case Code.eval_string(info) do # lock could be a keyword list {lock, _binding} when is_list(lock) -> Enum.into(lock, %{}) {lock, _binding} when is_map(lock) -> lock {nil, _binding} -> %{} end {:error, _} -> %{} end end @doc """ Receives a map and writes it as the latest lock. """ @spec write(map) :: :ok def write(map) do unless map == read do lines = for {app, rev} <- map, rev != nil do ~s("#{app}": #{inspect rev, limit: :infinity}) end File.write! lockfile, "%{" <> Enum.join(lines, ",\n ") <> "}\n" touch end :ok end defp lockfile do Mix.Project.config[:lockfile] end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/dep/umbrella.ex000066400000000000000000000032021254730255300227310ustar00rootroot00000000000000defmodule Mix.Dep.Umbrella do @moduledoc false @doc """ Gets all umbrella dependencies in unloaded format. """ def unloaded do config = Mix.Project.config if apps_path = config[:apps_path] do paths = Path.wildcard(Path.join(apps_path, "*")) build = Mix.Project.build_path paths |> Enum.filter(&File.dir?(&1)) |> extract_umbrella |> filter_umbrella(config[:apps]) |> to_umbrella_dep(build) else [] end end @doc """ Gets all umbrella dependencies in the loaded format. """ def loaded do deps = unloaded apps = Enum.map(deps, &(&1.app)) Enum.map(deps, fn umbrella_dep -> umbrella_dep = Mix.Dep.Loader.load(umbrella_dep, nil) deps = Enum.filter(umbrella_dep.deps, fn dep -> Mix.Dep.available?(dep) and dep.app in apps end) %{umbrella_dep | deps: deps} end) |> Mix.Dep.Converger.topsort end defp extract_umbrella(paths) do for path <- paths do app = path |> Path.basename |> String.downcase |> String.to_atom {app, path} end end defp filter_umbrella(pairs, nil), do: pairs defp filter_umbrella(pairs, apps) when is_list(apps) do for {app, _} = pair <- pairs, app in apps, do: pair end defp to_umbrella_dep(paths, build) do Enum.map paths, fn({app, path}) -> opts = [path: path, dest: Path.expand(path), from_umbrella: true, env: Mix.env, build: Path.join([build, "lib", Atom.to_string(app)])] %Mix.Dep{ scm: Mix.SCM.Path, app: app, requirement: nil, manager: :mix, status: {:ok, nil}, opts: opts} end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/exceptions.ex000066400000000000000000000032751254730255300225510ustar00rootroot00000000000000defmodule Mix.NoTaskError do defexception [:task, :message, :mix] def exception(opts) do task = opts[:task] %Mix.NoTaskError{task: task, message: msg(task)} end defp msg(task) do msg = "The task #{task} could not be found" case did_you_mean(task) do {similar, score} when score > 0.8 -> msg <> ". Did you mean '#{similar}'?" _otherwise -> msg end end defp did_you_mean(task) do Mix.Task.load_all # Ensure all tasks are loaded Mix.Task.all_modules |> Enum.map(&Mix.Task.task_name/1) |> Enum.reduce({nil, 0}, &max_similar(&1, task, &2)) end defp max_similar(source, target, {_, current} = best) do score = String.jaro_distance(source, target) if score < current, do: best, else: {source, score} end end defmodule Mix.InvalidTaskError do defexception [:task, :message, :mix] def exception(opts) do task = opts[:task] %Mix.InvalidTaskError{task: task, message: "The task #{task} does not export run/1"} end end defmodule Mix.ElixirVersionError do defexception [:target, :expected, :actual, :message, :mix] def exception(opts) do target = opts[:target] actual = opts[:actual] expected = opts[:expected] message = "You're trying to run #{inspect target} on Elixir v#{actual} but it " <> "has declared in its mix.exs file it supports only Elixir #{expected}" %Mix.ElixirVersionError{target: target, expected: expected, actual: actual, message: message} end end defmodule Mix.NoProjectError do defexception message: "Could not find a Mix.Project, please ensure a mix.exs file is available", mix: nil end defmodule Mix.Error do defexception [:mix, :message] end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/generator.ex000066400000000000000000000045321254730255300223530ustar00rootroot00000000000000defmodule Mix.Generator do @moduledoc """ Conveniences for working with paths and generating content. All of those functions are verbose, in the sense they log the action to be performed via `Mix.shell`. """ @doc """ Creates a file with the given contents. If the file already exists, asks for user confirmation. ## Options * `:force` - forces installation without a shell prompt. """ def create_file(path, contents, opts \\ []) when is_binary(path) do Mix.shell.info [:green, "* creating ", :reset, Path.relative_to_cwd(path)] if opts[:force] || Mix.Utils.overwriting?(path) do File.mkdir_p!(Path.dirname(path)) File.write!(path, contents) end end @doc """ Creates a directory if one does not exist yet. """ def create_directory(path) when is_binary(path) do Mix.shell.info [:green, "* creating ", :reset, Path.relative_to_cwd(path)] File.mkdir_p! path end @doc """ Embed a template given by `contents` into the current module. It will define a private function with the `name` followed by `_template` that expects assigns as arguments. This function must be invoked passing a keyword list. Each key in the keyword list can be accessed in the template using the `@` macro. For more information, check `EEx.SmartEngine`. """ defmacro embed_template(name, contents) do quote bind_quoted: binding do contents = case contents do [from_file: file] -> @file file File.read!(file) c when is_binary(c) -> @file {__ENV__.file, __ENV__.line+1} c _ -> raise ArgumentError, "expected string or from_file: file" end require EEx EEx.function_from_string :defp, :"#{name}_template", "<% _ = assigns %>" <> contents, [:assigns] end end @doc """ Embeds a text given by `contents` into the current module. It will define a private function with the `name` followed by `_text` that expects no argument. """ defmacro embed_text(name, contents) do quote bind_quoted: binding do contents = case contents do [from_file: f] -> File.read!(f) c when is_binary(c) -> c _ -> raise ArgumentError, "expected string or from_file: file" end defp unquote(:"#{name}_text")(), do: unquote(contents) end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/local.ex000066400000000000000000000036041254730255300214560ustar00rootroot00000000000000defmodule Mix.Local do @moduledoc false @doc """ The path for local archives. Check `mix archive` for info. """ def archives_path do System.get_env("MIX_ARCHIVES") || Path.join(Mix.Utils.mix_home, "archives") end @doc """ Append archives paths into Erlang code path. """ def append_archives do archives = archives_ebin() Enum.each(archives, &check_elixir_version_in_ebin/1) Enum.each(archives, &Code.append_path/1) end @doc """ Append mix paths into Erlang code path. """ def append_paths do Enum.each(Mix.Utils.mix_paths, &Code.append_path(&1)) end @doc """ Returns all tasks in local archives. """ def all_tasks do Mix.Task.load_tasks(archives_ebin()) end @doc """ Returns paths of all archive files matching given application name. """ def archive_files(name) do archives(name, ".ez") ++ archives(name, "-*.ez") end @doc """ Check Elixir version requirement stored in the archive and print a warning if it is not satisfied. """ def check_archive_elixir_version(path) do path |> Mix.Archive.ebin |> check_elixir_version_in_ebin() end defp archives(name, suffix) do archives_path() |> Path.join(name <> suffix) |> Path.wildcard end defp archives_ebin do Path.join(archives_path(), "*.ez") |> Path.wildcard |> Enum.map(&Mix.Archive.ebin/1) end defp check_elixir_version_in_ebin(ebin) do elixir = ebin |> Path.dirname |> Path.join(".elixir") |> String.to_char_list case :erl_prim_loader.get_file(elixir) do {:ok, req, _} -> unless Version.match?(System.version, req) do archive = ebin |> Path.dirname |> Path.basename Mix.shell.error "warning: the archive #{archive} requires Elixir #{inspect req} " <> "but you are running on v#{System.version}" end :ok :error -> :ok end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/project.ex000066400000000000000000000265071254730255300220410ustar00rootroot00000000000000defmodule Mix.Project do @moduledoc """ Defines and manipulate Mix projects. In order to configure Mix, a developer needs to use `Mix.Project` in a module and define a function named `project` that returns a keyword list with configuration. defmodule MyApp do use Mix.Project def project do [app: :my_app, version: "0.6.0"] end end After being defined, the configuration for this project can be read as `Mix.Project.config/0`. Notice that `config/0` won't fail if a project is not defined; this allows many mix tasks to work without a project. In case the developer needs a project or wants to access a special function in the project, the developer can call `Mix.Project.get!/0` which fails with `Mix.NoProjectError` in case a project is not defined. ## Erlang projects Mix can be used to manage Erlang projects that don't have any Elixir code. To ensure mix tasks work correctly for an Erlang project, `language: :erlang` has to be added to `project`. The setting also makes sure Elixir is not added as a dependency to the generated .app file or to the escript generated with `mix escript.build`, etc. """ @doc false defmacro __using__(_) do quote do @after_compile Mix.Project end end @private_config [:build_path, :app_path] # Invoked after each Mix.Project is compiled. @doc false def __after_compile__(env, _binary) do push env.module, env.file end # Push a project onto the project stack. # Only the top of the stack can be accessed. @doc false def push(atom, file \\ nil, app \\ nil) when is_atom(atom) do file = file || (atom && List.to_string(atom.__info__(:compile)[:source])) config = ([app: app] ++ default_config) |> Keyword.merge(get_project_config(atom)) |> Keyword.drop(@private_config) case Mix.ProjectStack.push(atom, config, file) do :ok -> :ok {:error, other} when is_binary(other) -> Mix.raise "Trying to load #{inspect atom} from #{inspect file}" <> " but another project with the same name was already defined at #{inspect other}" end end # Pops a project from the stack. @doc false def pop do Mix.ProjectStack.pop end # The configuration that is pushed down to dependencies. @doc false def deps_config(config \\ config()) do [build_embedded: config[:build_embedded], build_path: build_path(config), build_per_environment: config[:build_per_environment], consolidate_protocols: false, deps_path: deps_path(config)] end @doc """ Retrieves the current project if there is one. Otherwise `nil` is returned. It may happen in cases there is no mixfile in the current directory. If you expect a project to be defined, i.e. it is a requirement of the current task, you should call `get!/0` instead. """ def get do case Mix.ProjectStack.peek do %{name: name} -> name _ -> nil end end @doc """ Same as `get/0`, but raises an exception if there is no current project. This is usually called by tasks that need additional functions on the project to be defined. Since such tasks usually depend on a project being defined, this function raises `Mix.NoProjectError` in case no project is available. """ def get! do get || Mix.raise Mix.NoProjectError, [] end @doc """ Returns the project configuration. If there is no project defined, it still returns a keyword list with default values. This allows many mix tasks to work without the need for an underlying project. Note this configuration is cached once the project is pushed into the stack. Calling it multiple times won't cause it to be recomputed. Do not use `Mix.Project.config` to rely on runtime configuration. Use it only to configure aspects of your project (like compilation directories) and not your application runtime. """ def config do case Mix.ProjectStack.peek do %{config: config} -> config _ -> default_config end end @doc """ Returns a list of project configuration files for this project. This function is usually used in compilation tasks to trigger a full recompilation whenever such configuration files change. By default it includes the mix.exs file, the lock manifest and all config files in the `config` directory. """ def config_files do [Mix.Dep.Lock.manifest] ++ case Mix.ProjectStack.peek do %{config: config, file: file} -> configs = (config[:config_path] || "config/config.exs") |> Path.dirname |> Path.join("**/*.*") |> Path.wildcard |> Enum.reject(&String.starts_with?(Path.basename(&1), ".")) [file|configs] _ -> [] end end @doc """ Returns `true` if project is an umbrella project. """ def umbrella?(config \\ config()) do config[:apps_path] != nil end @doc """ Runs the given `fun` inside the given project. This function changes the current working directory and loads the project at the given directory onto the project stack. A `post_config` can be passed that will be merged into the project configuration. """ def in_project(app, path, post_config \\ [], fun) def in_project(app, ".", post_config, fun) do cached = try do load_project(app, post_config) rescue any -> Mix.shell.error "Error while loading project #{inspect app} at #{File.cwd!}" reraise any, System.stacktrace end try do fun.(cached) after Mix.Project.pop end end def in_project(app, path, post_config, fun) do File.cd! path, fn -> in_project(app, ".", post_config, fun) end end @doc """ Returns the path to store dependencies for this project. The returned path will be expanded. ## Examples Mix.Project.deps_path #=> "/path/to/project/deps" """ def deps_path(config \\ config()) do Path.expand config[:deps_path] end @doc """ Returns the build path for this project. The returned path will be expanded. ## Examples Mix.Project.build_path #=> "/path/to/project/_build/shared" If :build_per_environment is set to `true` (the default), it will create a new build per environment: Mix.env #=> :dev Mix.Project.build_path #=> "/path/to/project/_build/dev" """ def build_path(config \\ config()) do config[:build_path] || if config[:build_per_environment] do Path.expand("_build/#{Mix.env}") else Path.expand("_build/shared") end end @doc """ The path to store manifests. By default they are stored in the app path inside the build directory but it may be changed in future releases. The returned path will be expanded. ## Examples Mix.Project.manifest_path #=> "/path/to/project/_build/shared/lib/app" """ def manifest_path(config \\ config()) do app_path(config) end @doc """ Returns the application path inside the build. The returned path will be expanded. ## Examples Mix.Project.app_path #=> "/path/to/project/_build/shared/lib/app" """ def app_path(config \\ config()) do config[:app_path] || cond do app = config[:app] -> Path.join([build_path(config), "lib", Atom.to_string(app)]) config[:apps_path] -> Mix.raise "Trying to access app_path for an umbrella project but umbrellas have no app" true -> Mix.raise "Cannot access build without an application name, " <> "please ensure you are in a directory with a mix.exs file and it defines " <> "an :app name under the project configuration" end end @doc """ Returns the paths this project compiles to. The returned path will be expanded. ## Examples Mix.Project.compile_path #=> "/path/to/project/_build/shared/lib/app/ebin" """ def compile_path(config \\ config()) do Path.join(app_path(config), "ebin") end @doc """ Compiles the given project. It will run the compile task unless the project is in build embedded mode, which may fail as a explicit command to "mix compile" is required. """ def compile(args, config \\ config()) do if config[:build_embedded] do if not File.exists?(app_path(config)) do Mix.raise "Cannot execute task because the project was not yet compiled. " <> "When build_embedded is set to true, which is the default " <> "for production, `mix compile` must be explicitly executed" end :ok else Mix.Task.run "compile", args end end @doc """ Builds the project structure for the current application. ## Options * `:symlink_ebin` - symlink ebin instead of copying it """ def build_structure(config \\ config(), opts \\ []) do app = app_path(config) File.mkdir_p!(app) source = Path.expand("ebin") target = Path.join(app, "ebin") _ = cond do opts[:symlink_ebin] -> _ = symlink_or_copy(config, source, target) match?({:ok, _}, :file.read_link(target)) -> _ = File.rm_rf!(target) File.mkdir_p!(target) true -> File.mkdir_p!(target) end _ = symlink_or_copy(config, Path.expand("include"), Path.join(app, "include")) _ = symlink_or_copy(config, Path.expand("priv"), Path.join(app, "priv")) :ok end defp symlink_or_copy(config, source, target) do if config[:build_embedded] do if File.exists?(source) do File.rm_rf!(target) File.cp_r!(source, target) end else Mix.Utils.symlink_or_copy(source, target) end end @doc """ Ensures the project structure exists. In case it does, it is a no-op, otherwise, it is built. """ def ensure_structure(config \\ config(), opts \\ []) do if File.exists?(app_path(config)) do :ok else build_structure(config, opts) end end @doc """ Returns all load paths for this project. """ def load_paths(config \\ config()) do if umbrella?(config) do [] else [compile_path(config)] end end # Loads mix.exs in the current directory or loads the project from the # mixfile cache and pushes the project to the project stack. defp load_project(app, post_config) do Mix.ProjectStack.post_config(post_config) if cached = Mix.ProjectStack.read_cache(app) do {project, file} = cached push(project, file, app) project else file = Path.expand("mix.exs") old_proj = get() new_proj = if File.regular?(file) do _ = Code.load_file(file) case get() do ^old_proj -> Mix.raise "Could not find a Mix project at #{file}" new_proj -> new_proj end else file = "nofile" push(nil, file, app) nil end Mix.ProjectStack.write_cache(app, {new_proj, file}) new_proj end end defp default_config do [aliases: [], build_per_environment: true, build_embedded: false, default_task: "run", deps: [], deps_path: "deps", elixirc_paths: ["lib"], erlc_paths: ["src"], erlc_include_path: "include", erlc_options: [:debug_info], lockfile: "mix.lock", preferred_cli_env: [], start_permanent: false] end defp get_project_config(nil), do: [] defp get_project_config(atom), do: atom.project end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/project_stack.ex000066400000000000000000000077141254730255300232250ustar00rootroot00000000000000defmodule Mix.ProjectStack do @moduledoc false @timeout 30_000 @typep file :: binary @typep config :: Keyword.t @typep project :: {module, config, file} @spec start_link :: {:ok, pid} def start_link() do initial = %{stack: [], post_config: [], cache: HashDict.new} Agent.start_link fn -> initial end, name: __MODULE__ end @spec push(module, config, file) :: :ok | {:error, file} def push(module, config, file) do get_and_update fn %{stack: stack} = state -> # Consider the first children to always have io_done # because we don't need to print anything unless another # project talks ahold of the shell. io_done? = stack == [] config = Keyword.merge(config, state.post_config) project = %{name: module, config: config, file: file, pos: length(stack), recursing?: false, io_done: io_done?, tasks: HashSet.new} cond do file = find_project_named(module, stack) -> {{:error, file}, state} true -> {:ok, %{state | post_config: [], stack: [project|state.stack]}} end end end @spec pop() :: project | nil def pop do get_and_update fn %{stack: stack} = state -> case stack do [h|t] -> {take(h), %{state | stack: t}} [] -> {nil, state} end end end @spec peek() :: project | nil def peek do get fn %{stack: stack} -> case stack do [h|_] -> take(h) [] -> nil end end end @spec post_config(config) :: :ok def post_config(config) do cast fn state -> %{state | post_config: Keyword.merge(state.post_config, config)} end end @spec printable_app_name() :: atom | nil def printable_app_name do get_and_update fn %{stack: stack} = state -> case stack do [] -> {nil, state} [%{io_done: true}|_] -> {nil, state} [h|t] -> h = %{h | io_done: true} t = Enum.map(t, &%{&1 | io_done: false}) {h.config[:app], %{state | stack: [h|t]}} end end end @spec clear_stack() :: :ok def clear_stack do cast fn state -> %{state | stack: [], post_config: []} end end @doc """ Enables the recursion for the project at the top of the stack. Returns `true` if recursion was enabled or `false` if the project already had recursion enabled or there is no project in the stack. """ @spec enable_recursion :: boolean def enable_recursion do get_and_update fn %{stack: stack} = state -> case stack do [h|t] -> {not h.recursing?, %{state | stack: [%{h | recursing?: true}|t]}} _ -> {false, state} end end end @doc """ Disables the recursion for the project in the stack. Returns `true` if recursion was disabled or `false` if there is no project or recursion was not enabled. """ @spec disable_recursion :: boolean def disable_recursion do get_and_update fn %{stack: stack} = state -> case stack do [h|t] -> {h.recursing?, %{state | stack: [%{h | recursing?: false}|t]}} _ -> {false, state} end end end @spec read_cache(term) :: term def read_cache(key) do get fn %{cache: cache} -> cache[key] end end @spec write_cache(term, term) :: :ok def write_cache(key, value) do cast fn state -> %{state | cache: Dict.put(state.cache, key, value)} end end @spec clear_cache :: :ok def clear_cache do cast fn state -> %{state | cache: HashDict.new} end end defp find_project_named(name, stack) do name && Enum.find_value(stack, fn %{name: n, file: file} when n === name -> file %{} -> nil end) end defp take(h) do Map.take(h, [:name, :config, :file, :pos]) end defp get_and_update(fun) do Agent.get_and_update __MODULE__, fun, @timeout end defp get(fun) do Agent.get __MODULE__, fun, @timeout end defp cast(fun) do Agent.cast __MODULE__, fun end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/rebar.ex000066400000000000000000000103511254730255300214540ustar00rootroot00000000000000defmodule Mix.Rebar do @moduledoc false @doc """ Returns the path supposed to host the local copy of rebar. """ def local_rebar_path, do: Path.join(Mix.Utils.mix_home, "rebar") @doc """ Returns the path to the global copy of rebar, if one exists. """ def global_rebar_cmd do wrap_cmd System.find_executable("rebar") end @doc """ Returns the path to the local copy of rebar, if one exists. """ def local_rebar_cmd do rebar = local_rebar_path wrap_cmd(if File.regular?(rebar), do: rebar) end @doc """ Returns the path to the available rebar command. """ def rebar_cmd do global_rebar_cmd || local_rebar_cmd end @doc """ Loads the rebar.config and evaluates rebar.config.script if it exists in the given directory. """ def load_config(dir) do config_path = Path.join(dir, "rebar.config") script_path = Path.join(dir, "rebar.config.script") config = case :file.consult(config_path) do {:ok, config} -> config {:error, :enoent} -> [] {:error, error} -> reason = :file.format_error(error) Mix.raise "Error consulting rebar config #{config_path}: #{reason}" end if File.exists?(script_path) do eval_script(script_path, config) else config end end @doc """ Parses the dependencies in given rebar.config to Mix's dependency format. """ def deps(config) do if deps = config[:deps] do deps_dir = config[:deps_dir] || "deps" Enum.map(deps, &parse_dep(&1, deps_dir)) else [] end end @doc """ Runs `fun` for the given config and for each `sub_dirs` in the given rebar config. """ def recur(config, fun) when is_binary(config) do recur(load_config(config), fun) end def recur(config, fun) do subs = (config[:sub_dirs] || []) |> Enum.map(&Path.wildcard(&1)) |> Enum.concat |> Enum.filter(&File.dir?(&1)) |> Enum.map(&recur(&1, fun)) |> Enum.concat [fun.(config)|subs] end defp parse_dep({app, req}, deps_dir) do {app, compile_req(req), [path: Path.join(deps_dir, Atom.to_string(app))]} end defp parse_dep({app, req, source}, deps_dir) do parse_dep({app, req, source, []}, deps_dir) end defp parse_dep({app, req, source, opts}, _deps_dir) do [scm, url | source] = Tuple.to_list(source) mix_opts = [{scm, to_string(url)}] ref = case source do [""|_] -> [branch: "HEAD"] [{:branch, branch}|_] -> [branch: to_string(branch)] [{:tag, tag}|_] -> [tag: to_string(tag)] [{:ref, ref}|_] -> [ref: to_string(ref)] [ref|_] -> [ref: to_string(ref)] _ -> [] end mix_opts = mix_opts ++ ref if :proplists.get_value(:raw, opts, false) do mix_opts = mix_opts ++ [compile: false] end {app, compile_req(req), mix_opts} end defp parse_dep(app, deps_dir) do parse_dep({app, ".*"}, deps_dir) end defp compile_req(req) do case Regex.compile to_string(req) do {:ok, re} -> re {:error, reason} -> Mix.raise "Unable to compile version regex: \"#{req}\", #{reason}" end end defp eval_script(script_path, config) do script = Path.basename(script_path) |> String.to_char_list result = File.cd!(Path.dirname(script_path), fn -> :file.script(script, eval_binds(CONFIG: config, SCRIPT: script)) end) case result do {:ok, config} -> config {:error, error} -> reason = :file.format_error(error) Mix.shell.error("Error evaluating rebar config script #{script_path}: #{reason}") Mix.shell.error("You may solve this issue by adding rebar as a dependency to your project") Mix.shell.error("Any dependency defined in the script won't be available " <> "unless you add them to your Mix project") config end end defp eval_binds(binds) do Enum.reduce(binds, :erl_eval.new_bindings, fn ({k, v}, binds) -> :erl_eval.add_binding(k, v, binds) end) end defp wrap_cmd(nil), do: nil defp wrap_cmd(rebar) do if match?({:win32, _}, :os.type) and not String.ends_with?(rebar, ".cmd") do "escript.exe \"#{rebar}\"" else rebar end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/remote_converger.ex000066400000000000000000000016321254730255300237300ustar00rootroot00000000000000defmodule Mix.RemoteConverger do @moduledoc false use Behaviour # A remote converger returns updated dependencies with # extra information that can be used during mix's converging. # Useful for things like external package managers @doc """ Return `true` if given dependency is handled by remote converger. """ defcallback remote?(Mix.Dep.t) :: boolean @doc """ Run the remote converger. Return updated lock. """ defcallback converge([Mix.Dep.t], map) :: map @doc """ Returns child dependencies the converger has for the dependency. This list should filter the loaded children. """ defcallback deps(Mix.Dep.t, map) :: [atom] @doc """ Get registered remote converger. """ def get do Mix.State.get(:remote_converger) end @doc """ Register a remote converger. """ def register(mod) when is_atom(mod) do Mix.State.put(:remote_converger, mod) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/scm.ex000066400000000000000000000076731254730255300211600ustar00rootroot00000000000000defmodule Mix.SCM do use Behaviour @type opts :: Keyword.t @moduledoc """ This module provides helper functions and defines the behaviour required by any SCM used by mix. """ @doc """ Returns a boolean if the dependency can be fetched or it is meant to be previously available in the filesystem. Local dependencies (i.e. non fetchable ones) are automatically recompiled every time the parent project is compiled. """ defcallback fetchable? :: boolean @doc """ Returns a string representing the SCM. This is used when printing the dependency and not for inspection, so the amount of information should be concise and easy to spot. """ defcallback format(opts) :: String.t @doc """ Returns a string representing the SCM. This is used when printing the dependency and not for inspection, so the amount of information should be concise and easy to spot. If nil is returned, it means no lock information is available. """ defcallback format_lock(opts) :: String.t | nil @doc """ This behaviour function receives a keyword list of `opts` and should return an updated list in case the SCM consumes the available options. For example, when a developer specifies a dependency: {:foo, "0.1.0", github: "foo/bar"} Each registered SCM will be asked if they consume this dependency, receiving `[github: "foo/bar"]` as argument. Since this option makes sense for the Git SCM, it will return an update list of options while other SCMs would simply return `nil`. """ defcallback accepts_options(app :: atom, opts) :: opts | nil @doc """ This behaviour function returns a boolean if the dependency is available. """ defcallback checked_out?(opts) :: boolean @doc """ This behaviour function checks out dependencies. If the dependency is locked, a lock is received in `opts` and the repository must be check out at the lock. Otherwise, no lock is given and the repository can be checked out to the latest version. It must return the current lock. """ defcallback checkout(opts) :: any @doc """ This behaviour function updates dependencies. It may be called by `deps.get` or `deps.update`. In the first scenario, a lock is received in `opts` and the repository must be updated to the lock. In the second, no lock is given and the repository can be updated freely. It must return the current lock. """ defcallback update(opts) :: any @doc """ This behaviour function checks the status of the lock. In particular, it checks if the revision stored in the lock is the same as the repository it is currently in. It may return: * `:mismatch` - if the lock doesn't match and we need to simply move to the latest lock * `:outdated` - the repository options are outdated in the lock and we need to trigger a full update * `:ok` - everything is fine The lock is sent via `opts[:lock]` but it may not always be available. In such cases, if the SCM requires a lock, it must return `:lockmismatch`, otherwise simply `:ok`. Note the lock may also belong to another SCM and as such, an structural check is required. A structural mismatch should always return `:outdated`. """ defcallback lock_status(opts) :: :mismatch | :outdated | :ok @doc """ Receives two options and must return `true` if they refer to the same repository. The options are guaranteed to belong to the same SCM. """ defcallback equal?(opts1 :: opts, opts2 :: opts) :: boolean @doc """ Returns all available SCMs. Each SCM is tried in order until a matching one is found. """ def available do {:ok, scm} = Mix.State.fetch(:scm) scm end @doc """ Prepend the given SCM module to the list of available SCMs. """ def prepend(mod) when is_atom(mod) do Mix.State.prepend(:scm, mod) end @doc """ Append the given SCM module to the list of available SCMs. """ def append(mod) when is_atom(mod) do Mix.State.append(:scm, mod) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/scm/000077500000000000000000000000001254730255300206055ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/scm/git.ex000066400000000000000000000121631254730255300217310ustar00rootroot00000000000000defmodule Mix.SCM.Git do @behaviour Mix.SCM @moduledoc false def fetchable? do true end def format(opts) do opts[:git] end def format_lock(opts) do case opts[:lock] do {:git, _, lock_rev, lock_opts} -> lock = String.slice(lock_rev, 0, 7) case Enum.find_value [:branch, :ref, :tag], &List.keyfind(lock_opts, &1, 0) do {:ref, _} -> lock <> " (ref)" {key, val} -> lock <> " (#{key}: #{val})" nil -> lock end _ -> nil end end def accepts_options(_app, opts) do cond do gh = opts[:github] -> opts |> Keyword.delete(:github) |> Keyword.put(:git, "https://github.com/#{gh}.git") opts[:git] -> opts true -> nil end end def checked_out?(opts) do # Are we inside a git repository? File.regular?(Path.join(opts[:dest], ".git/HEAD")) end def lock_status(opts) do assert_git case opts[:lock] do {:git, lock_repo, lock_rev, lock_opts} -> File.cd!(opts[:dest], fn -> rev_info = get_rev_info cond do not git_repos_match?(lock_repo, opts[:git]) -> :outdated lock_opts != get_lock_opts(opts) -> :outdated lock_rev != rev_info[:rev] -> :mismatch lock_repo != rev_info[:origin] -> :outdated true -> :ok end end) nil -> :mismatch _ -> :outdated end end def equal?(opts1, opts2) do git_repos_match?(opts1[:git], opts2[:git]) && get_lock_opts(opts1) == get_lock_opts(opts2) end def checkout(opts) do assert_git path = opts[:dest] location = opts[:git] _ = File.rm_rf!(path) git!(~s(clone --no-checkout --progress "#{location}" "#{path}")) File.cd! path, fn -> do_checkout(opts) end end def update(opts) do assert_git File.cd! opts[:dest], fn -> # Ensures origin is set the lock repo location = opts[:git] update_origin(location) command = "--git-dir=.git fetch --force" if {1, 7, 1} <= git_version() do command = command <> " --progress" end if opts[:tag] do command = command <> " --tags" end git!(command) do_checkout(opts) end end ## Helpers defp do_checkout(opts) do ref = get_lock_rev(opts[:lock]) || get_opts_rev(opts) git!("--git-dir=.git checkout --quiet #{ref}") if opts[:submodules] do git!("--git-dir=.git submodule update --init --recursive") end get_lock(opts) end defp get_lock(opts) do rev_info = get_rev_info() {:git, opts[:git], rev_info[:rev], get_lock_opts(opts)} end defp get_lock_rev({:git, _repo, lock, _opts}) when is_binary(lock), do: lock defp get_lock_rev(_), do: nil defp get_lock_opts(opts) do lock_opts = Enum.find_value [:branch, :ref, :tag], &List.keyfind(opts, &1, 0) lock_opts = List.wrap(lock_opts) if opts[:submodules] do lock_opts ++ [submodules: true] else lock_opts end end defp get_opts_rev(opts) do if branch = opts[:branch] do "origin/#{branch}" else opts[:ref] || opts[:tag] || "origin/master" end end defp get_rev_info do destructure [origin, rev], :os.cmd('git --git-dir=.git config remote.origin.url && git --git-dir=.git rev-parse --verify --quiet HEAD') |> IO.iodata_to_binary |> String.split("\n", trim: true) [origin: origin, rev: rev] end defp update_origin(location) do git!(~s(--git-dir=.git config remote.origin.url "#{location}")) :ok end defp git!(command) do if Mix.shell.cmd("git " <> command) != 0 do Mix.raise "Command `git #{command}` failed" end :ok end defp assert_git do case Mix.State.fetch(:git_available) do {:ok, true} -> :ok :error -> if System.find_executable("git") do Mix.State.put(:git_available, true) else Mix.raise "Error fetching/updating Git repository: the `git` " <> "executable is not available in your PATH. Please install " <> "Git on this machine or pass --no-deps-check if you want to " <> "run a previously built application on a system without Git." end end end defp git_version do case Mix.State.fetch(:git_version) do {:ok, version} -> version :error -> version = :os.cmd('git --version') |> IO.iodata_to_binary |> parse_version Mix.State.put(:git_version, version) version end end defp git_repos_match?(repo_a, repo_b) do normalize_github_repo(repo_a) == normalize_github_repo(repo_b) end # TODO: Remove this on Elixir v2.0 to push everyone to https defp normalize_github_repo("git://github.com/" <> rest), do: "https://github.com/#{rest}" defp normalize_github_repo(repo), do: repo defp parse_version("git version " <> version) do String.split(version, ".") |> Enum.take(3) |> Enum.map(&to_integer/1) |> List.to_tuple end defp to_integer(string) do {int, _} = Integer.parse(string) int end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/scm/path.ex000066400000000000000000000016521254730255300221030ustar00rootroot00000000000000defmodule Mix.SCM.Path do @behaviour Mix.SCM @moduledoc false def fetchable? do false end def format(opts) do opts[:path] end def format_lock(_opts) do nil end def accepts_options(app, opts) do cond do raw = opts[:path] -> Keyword.put opts, :dest, Path.expand(raw) opts[:in_umbrella] -> path = "../#{app}" opts |> Keyword.put(:dest, Path.expand(path)) |> Keyword.put_new(:path, path) |> Keyword.put_new(:env, Mix.env) true -> nil end end def checked_out?(opts) do File.dir?(opts[:dest]) end def lock_status(_opts) do :ok end def equal?(opts1, opts2) do opts1[:dest] == opts2[:dest] end def checkout(opts) do path = Path.relative_to_cwd opts[:dest] Mix.raise "Cannot checkout path dependency, expected a dependency at #{path}" end def update(opts) do opts[:lock] end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/shell.ex000066400000000000000000000057731254730255300215040ustar00rootroot00000000000000defmodule Mix.Shell do @moduledoc """ Defines Mix.Shell contract. """ use Behaviour @doc """ Informs the given message. """ defcallback info(message :: IO.ANSI.ansidata) :: any @doc """ Warns about the given error message. """ defcallback error(message :: IO.ANSI.ansidata) :: any @doc """ Prompts the user for input. """ defcallback prompt(message :: String.t) :: String.t @doc """ Asks the user for confirmation. """ defcallback yes?(message :: String.t) :: boolean @doc """ Executes the given command and returns its exit status. """ defcallback cmd(command :: String.t) :: integer @doc """ Executes the given command and returns its exit status. ## Options * `:print_app` - when `false`, does not print the app name when the command outputs something * `:stderr_to_stdout` - when `false`, does not redirect stderr to stdout * `:quiet` - when `true`, do not print the command output """ defcallback cmd(command :: String.t, options :: Keyword.t) :: integer @doc """ Prints the current application to shell if it was not printed yet. """ defcallback print_app() :: any @doc """ Returns the printable app name. This function returns the current application name but only if the application name should be printed. Calling this function automatically toggles its value to `false` until the current project is re-entered. The goal is to exactly avoid printing the application name multiple times. """ def printable_app_name do Mix.ProjectStack.printable_app_name end @doc """ An implementation of the command callback that is shared across different shells. """ def cmd(command, options \\ [], callback) do args = if Keyword.get(options, :stderr_to_stdout, true) do [:stderr_to_stdout] else [] end callback = if Keyword.get(options, :quiet, false) do fn x -> x end else callback end port = Port.open({:spawn, shell_command(command)}, [:stream, :binary, :exit_status, :hide, :use_stdio|args]) do_cmd(port, callback) end defp do_cmd(port, callback) do receive do {^port, {:data, data}} -> callback.(data) do_cmd(port, callback) {^port, {:exit_status, status}} -> status end end # Finding shell command logic from :os.cmd in OTP # https://github.com/erlang/otp/blob/8deb96fb1d017307e22d2ab88968b9ef9f1b71d0/lib/kernel/src/os.erl#L184 defp shell_command(command) do case :os.type do {:unix, _} -> command = command |> String.replace("\"", "\\\"") |> :binary.bin_to_list 'sh -c "' ++ command ++ '"' {:win32, osname} -> command = :binary.bin_to_list(command) case {System.get_env("COMSPEC"), osname} do {nil, :windows} -> 'command.com /c ' ++ command {nil, _} -> 'cmd /c ' ++ command {cmd, _} -> '#{cmd} /c ' ++ command end end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/shell/000077500000000000000000000000001254730255300211325ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/shell/io.ex000066400000000000000000000032001254730255300220720ustar00rootroot00000000000000defmodule Mix.Shell.IO do @moduledoc """ This is Mix's default shell. It simply prints messages to stdio and stderr. """ @behaviour Mix.Shell @doc """ Prints the currently running application if it was not printed yet. """ def print_app do if name = Mix.Shell.printable_app_name do IO.puts "==> #{name}" end end @doc """ Executes the given command and prints its output to stdout as it comes. """ def cmd(command, opts \\ []) do print_app? = Keyword.get(opts, :print_app, true) Mix.Shell.cmd(command, opts, fn data -> if print_app?, do: print_app() IO.write(data) end) end @doc """ Writes a message to the shell followed by new line. """ def info(message) do print_app IO.puts IO.ANSI.format message end @doc """ Writes an error message to the shell followed by new line. """ def error(message) do print_app IO.puts :stderr, IO.ANSI.format(red(message)) end @doc """ Writes a message shell followed by prompting the user for input. Input will be consumed until enter is pressed. """ def prompt(message) do print_app IO.gets message <> " " end @doc """ Receives a message and asks the user if they want to proceed. The user must press enter or type anything that matches the "yes" regex `~r/^Y(es)?$/i`. """ def yes?(message) do print_app got_yes? IO.gets(message <> " [Yn] ") end defp got_yes?(answer) when is_binary(answer) do answer =~ ~r/^(Y(es)?)?$/i end # The io server may return :eof or :error defp got_yes?(_), do: false defp red(message) do [:red, :bright, message] end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/shell/process.ex000066400000000000000000000060421254730255300231500ustar00rootroot00000000000000defmodule Mix.Shell.Process do @moduledoc """ This is a Mix shell that uses the current process mailbox for communication instead of IO. When a developer calls `info("hello")`, the following message will be sent to the current process: {:mix_shell, :info, ["hello"]} This is mainly useful in tests, allowing us to assert if given messages were received or not. Since we need to guarantee a clean slate between tests, there is also a `flush/1` function responsible for flushing all `:mix_shell` related messages from the process inbox. """ @behaviour Mix.Shell @doc """ Flush all `:mix_shell` and `:mix_shell_input` messages from the current process. If a callback is given, it is invoked for each received message. ## Examples flush &IO.inspect(&1) """ def flush(callback \\ fn(x) -> x end) do receive do {:mix_shell, _, _} = message -> callback.(message) flush(callback) {:mix_shell_input, _, _} = message -> callback.(message) flush(callback) after 0 -> :done end end @doc """ Prints the currently running application if it was not printed yet. """ def print_app do if name = Mix.Shell.printable_app_name do send self, {:mix_shell, :info, ["==> #{name}"]} end end @doc """ Executes the given command and forwards its messages to the current process. """ def cmd(command, opts \\ []) do print_app? = Keyword.get(opts, :print_app, true) Mix.Shell.cmd(command, opts, fn(data) -> if print_app?, do: print_app() send self, {:mix_shell, :run, [data]} end) end @doc """ Forwards the message to the current process. """ def info(message) do print_app send self, {:mix_shell, :info, [format(message)]} end @doc """ Forwards the message to the current process. """ def error(message) do print_app send self, {:mix_shell, :error, [format(message)]} end defp format(message) do message |> IO.ANSI.format(false) |> IO.iodata_to_binary end @doc """ Forwards the message to the current process. It also checks the inbox for an input message matching: {:mix_shell_input, :prompt, value} If one does not exist, it will abort since there was no shell process inputs given. Value must be a string. """ def prompt(message) do print_app send self, {:mix_shell, :prompt, [message]} receive do {:mix_shell_input, :prompt, response} -> response after 0 -> raise "No shell process input given for prompt/1" end end @doc """ Forwards the message to the current process. It also checks the inbox for an input message matching: {:mix_shell_input, :yes?, value} If one does not exist, it will abort since there was no shell process inputs given. Value must be `true` or `false`. """ def yes?(message) do print_app send self, {:mix_shell, :yes?, [message]} receive do {:mix_shell_input, :yes?, response} -> response after 0 -> raise "No shell process input given for yes?/1" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/state.ex000066400000000000000000000014321254730255300215010ustar00rootroot00000000000000defmodule Mix.State do @moduledoc false @name __MODULE__ def start_link() do Agent.start_link(__MODULE__, :init, [], [name: @name]) end def init() do %{shell: Mix.Shell.IO, env: String.to_atom(System.get_env("MIX_ENV") || "dev"), scm: [Mix.SCM.Git, Mix.SCM.Path]} end def fetch(key) do Agent.get(@name, Map, :fetch, [key]) end def get(key, default \\ nil) do Agent.get(@name, Map, :get, [key, default]) end def put(key, value) do Agent.update(@name, Map, :put, [key, value]) end def prepend(key, value) do Agent.update(@name, Map, :update, [key, [value], &[value|List.delete(&1, value)]]) end def append(key, value) do Agent.update(@name, Map, :update, [key, [value], &(List.delete(&1, value) ++ [value])]) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/task.ex000066400000000000000000000214051254730255300213250ustar00rootroot00000000000000defmodule Mix.Task do use Behaviour @moduledoc """ A simple module that provides conveniences for creating, loading and manipulating tasks. A Mix task can be defined by simply using `Mix.Task` in a module starting with `Mix.Tasks.` and defining the `run/1` function: defmodule Mix.Tasks.Hello do use Mix.Task def run(_) do Mix.shell.info "hello" end end The `run/1` function will receive all arguments passed to the command line. ## Attributes There are a couple attributes available in Mix tasks to configure them in Mix: * `@shortdoc` - makes the task public with a short description that appears on `mix help` * `@recursive` - run the task recursively in umbrella projects """ @type task_name :: String.t | atom @type task_module :: atom @doc """ A task needs to implement `run` which receives a list of command line args. """ defcallback run([binary]) :: any @doc false defmacro __using__(_opts) do quote do Enum.each [:shortdoc, :recursive], &Module.register_attribute(__MODULE__, &1, persist: true) @behaviour Mix.Task end end @doc """ Loads all tasks in all code paths. """ @spec load_all() :: [task_module] def load_all, do: load_tasks(:code.get_path) @doc """ Loads all tasks in the given `paths`. """ @spec load_tasks([List.Chars.t]) :: [task_module] def load_tasks(dirs) do # We may get duplicate modules because we look through the # entire load path so make sure we only return unique modules. for(dir <- dirs, {:ok, files} = :erl_prim_loader.list_dir(to_char_list(dir)), file <- files, mod = task_from_path(file), do: mod) |> Enum.uniq end @prefix_size byte_size("Elixir.Mix.Tasks.") @suffix_size byte_size(".beam") defp task_from_path(filename) do base = Path.basename(filename) part = byte_size(base) - @prefix_size - @suffix_size case base do <<"Elixir.Mix.Tasks.", rest :: binary-size(part), ".beam">> -> mod = :"Elixir.Mix.Tasks.#{rest}" ensure_task?(mod) && mod _ -> nil end end @doc """ Returns all loaded task modules. Modules that are not yet loaded won't show up. Check `load_all/0` if you want to preload all tasks. """ @spec all_modules() :: [task_module] def all_modules do for {module, _} <- :code.all_loaded, task?(module), do: module end @doc """ Gets the moduledoc for the given task `module`. Returns the moduledoc or `nil`. """ @spec moduledoc(task_module) :: String.t | nil def moduledoc(module) when is_atom(module) do case Code.get_docs(module, :moduledoc) do {_line, moduledoc} -> moduledoc nil -> nil end end @doc """ Gets the shortdoc for the given task `module`. Returns the shortdoc or `nil`. """ @spec shortdoc(task_module) :: String.t | nil def shortdoc(module) when is_atom(module) do case List.keyfind module.__info__(:attributes), :shortdoc, 0 do {:shortdoc, [shortdoc]} -> shortdoc _ -> nil end end @doc """ Checks if the task should be run recursively for all sub-apps in umbrella projects. Returns `true` or `false`. """ @spec recursive(task_module) :: boolean def recursive(module) when is_atom(module) do case List.keyfind module.__info__(:attributes), :recursive, 0 do {:recursive, [setting]} -> setting _ -> false end end @doc """ Returns the task name for the given `module`. """ @spec task_name(task_module) :: task_name def task_name(module) when is_atom(module) do Mix.Utils.module_name_to_command(module, 2) end @doc """ Checks if exists an alias with the given task name. """ @spec alias?(task_name) :: boolean def alias?(task) when is_binary(task) do alias?(String.to_atom(task)) end def alias?(task) when is_atom(task) do Mix.Project.config[:aliases][task] end @doc """ Receives a task name and returns the task module if found. Otherwise returns `nil` in case the module exists but it isn't a task or cannot be found. """ @spec get(task_name) :: task_module | nil def get(task) do case fetch(task) do {:ok, module} -> module {:error, _} -> nil end end @doc """ Receives a task name and retrieves the task module. ## Exceptions * `Mix.NoTaskError` - raised if the task could not be found * `Mix.InvalidTaskError` - raised if the task is not a valid `Mix.Task` """ @spec get!(task_name) :: task_module | no_return def get!(task) do case fetch(task) do {:ok, module} -> module {:error, :invalid} -> Mix.raise Mix.InvalidTaskError, task: task {:error, :not_found} -> Mix.raise Mix.NoTaskError, task: task end end defp fetch(task) when is_binary(task) or is_atom(task) do case Mix.Utils.command_to_module(to_string(task), Mix.Tasks) do {:module, module} -> if task?(module), do: {:ok, module}, else: {:error, :invalid} {:error, _} -> {:error, :not_found} end end @doc """ Runs a `task` with the given `args`. If the task was not yet invoked, it runs the task and returns the result. If there is an alias with the same name, the alias will be invoked instead of a task. If the task or alias were already invoked, it does not run them again and simply aborts with `:noop`. It may raise an exception if an alias or a task can't be found or the task is invalid. Check `get!/1` for more information. """ @spec run(task_name, [any]) :: any def run(task, args \\ []) def run(task, args) when is_atom(task) do run(Atom.to_string(task), args) end def run(task, args) when is_binary(task) do proj = Mix.Project.get alias = Mix.Project.config[:aliases][String.to_atom(task)] cond do alias && Mix.TasksServer.run({:alias, task, proj}) -> res = run_alias(List.wrap(alias), args, :ok) Mix.TasksServer.put({:task, task, proj}) res Mix.TasksServer.run({:task, task, proj}) -> run_task(proj, task, args) true -> :noop end end defp run_task(proj, task, args) do module = get(task) # If the task is not available, let's try to compile the project unless module do if proj, do: Mix.Project.compile([]) module = get!(task) end if recursive(module) and Mix.Project.umbrella? and Mix.ProjectStack.enable_recursion do res = recur(fn _ -> run(task, args) end) Mix.ProjectStack.disable_recursion res else Mix.TasksServer.put({:task, task, proj}) module.run(args) end end defp run_alias([h|t], alias_args, _res) when is_binary(h) do [task|args] = OptionParser.split(h) res = Mix.Task.run task, join_args(args, alias_args, t) run_alias(t, alias_args, res) end defp run_alias([h|t], alias_args, _res) when is_function(h, 1) do res = h.(join_args([], alias_args, t)) run_alias(t, alias_args, res) end defp run_alias([], _alias_task, res) do res end defp join_args(args, alias_args, []), do: args ++ alias_args defp join_args(args, _alias_args, _), do: args @doc """ Clears all invoked tasks, allowing them to be reinvoked. This operation is not recursive. """ @spec clear :: :ok def clear do Mix.TasksServer.clear end @doc """ Reenables a given task so it can be executed again down the stack. Both alias and the regular stack are reenabled when this function is called. If an umbrella project reenables a task, it is reenabled for all children projects. """ @spec reenable(task_name) :: :ok def reenable(task) when is_binary(task) or is_atom(task) do task = to_string(task) proj = Mix.Project.get Mix.TasksServer.delete_many([{:task, task, proj}, {:alias, task, proj}]) _ = if (module = get(task)) && recursive(module) && Mix.Project.umbrella? do recur fn proj -> Mix.TasksServer.delete_many([{:task, task, proj}, {:alias, task, proj}]) end end :ok end defp recur(fun) do # Get all dependency configuration but not the deps path # as we leave the control of the deps path still to the # umbrella child. config = Mix.Project.deps_config |> Keyword.delete(:deps_path) for %Mix.Dep{app: app, opts: opts} <- Mix.Dep.Umbrella.loaded do Mix.Project.in_project(app, opts[:path], config, fun) end end @doc """ Returns `true` if given module is a task. """ @spec task?(task_module) :: boolean() def task?(module) when is_atom(module) do match?('Elixir.Mix.Tasks.' ++ _, Atom.to_char_list(module)) and ensure_task?(module) end defp ensure_task?(module) do Code.ensure_loaded?(module) and function_exported?(module, :run, 1) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/000077500000000000000000000000001254730255300211505ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/app.start.ex000066400000000000000000000054031254730255300234240ustar00rootroot00000000000000defmodule Mix.Tasks.App.Start do use Mix.Task @shortdoc "Start all registered apps" @moduledoc """ Starts all registered apps. The application is started by default as temporary. In case `:start_permanent` is set to true in your project configuration or the `--permanent` flag is given, it is started as permanent, which guarantee the node will shutdown in case the application crashes permanently. ## Command line options * `--force` - force compilation regardless of compilation times * `--temporary` - start the application as temporary * `--permanent` - start the application as permanent * `--no-compile` - do not compile even if files require compilation * `--no-protocols` - do not load consolidated protocols * `--no-deps-check` - do not check dependencies * `--no-elixir-version-check` - do not check elixir version * `--no-start` - do not start applications after compilation """ @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! {opts, _, _} = OptionParser.parse args, switches: [permanent: :boolean, temporary: :boolean] Mix.Task.run "loadpaths", args unless "--no-compile" in args do Mix.Project.compile(args) end unless "--no-protocols" in args do path = Path.join(Mix.Project.build_path, "consolidated") if File.dir?(path) do Code.prepend_path(path) Enum.each(File.ls!(path), fn file -> module = file |> Path.rootname() |> String.to_atom() :code.purge(module) :code.delete(module) end) end end unless "--no-start" in args do # Stop the Logger when starting the application as it is # up to the application to decide if it should be restarted # or not. # # Mix should not depend directly on Logger so check that it's loaded. if Process.whereis(Logger), do: Logger.App.stop() start(Mix.Project.config, opts) end :ok end @doc false def start(config, opts) do apps = cond do Mix.Project.umbrella?(config) -> for %Mix.Dep{app: app} <- Mix.Dep.Umbrella.loaded, do: app app = config[:app] -> [app] true -> [] end type = type(config, opts) Enum.each apps, &ensure_all_started(&1, type) end defp ensure_all_started(app, type) do case Application.ensure_all_started(app, type) do {:ok, _} -> :ok {:error, {app, reason}} -> Mix.raise "Could not start application #{app}: " <> Application.format_error(reason) end end @doc false def type(config, opts) do cond do opts[:temporary] -> :temporary opts[:permanent] -> :permanent config[:start_permanent] -> :permanent true -> :temporary end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/archive.build.ex000066400000000000000000000046031254730255300242300ustar00rootroot00000000000000defmodule Mix.Tasks.Archive.Build do use Mix.Task @shortdoc "Archive this project into a .ez file" @moduledoc """ Builds an archive according to the specification of the [Erlang Archive Format](http://www.erlang.org/doc/man/code.html). The archive will be created in the current directory (which is expected to be the project root), unless an argument `-o` is provided with the file name. Archives are meant to bundle small projects, usually installed locally. By default, this command archives the current project but the `-i` and `-o` options can be used to archive any directory. For example, `mix archive.build` with no options translates to: mix archive.build -i _build/ENV/lib/APP -o APP-VERSION.ez ## Command line options * `-o` - specify output file name. If there is a `mix.exs`, defaults to `APP-VERSION.ez`. * `-i` - specify the input directory to archive. If there is a `mix.exs`, defaults to the current application build. * `--no-compile` - skip compilation. Only applies when `mix.exs` is available. """ @spec run(OptionParser.argv) :: :ok def run(args) do {opts, _, _} = OptionParser.parse(args, aliases: [o: :output, i: :input], switches: [force: :boolean, compile: :boolean]) project = Mix.Project.get if project && Keyword.get(opts, :compile, true) do Mix.Task.run :compile, args end source = cond do input = opts[:input] -> input project -> path = Mix.Project.app_path if elixir = Mix.Project.config[:elixir] do File.write Path.join(path, ".elixir"), elixir else File.rm Path.join(path, ".elixir") end path true -> Mix.raise "Cannot create archive without input directory, " <> "please pass -i as an option" end target = cond do output = opts[:output] -> output app = Mix.Project.config[:app] -> Mix.Archive.name(app, Mix.Project.config[:version]) true -> Mix.raise "Cannot create archive without output file, " <> "please pass -o as an option" end unless File.dir?(source) do Mix.raise "Expected archive source #{inspect source} to be a directory" end Mix.Archive.create(source, target) Mix.shell.info "Generated archive #{target} with MIX_ENV=#{Mix.env}" :ok end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/archive.ex000066400000000000000000000016341254730255300231330ustar00rootroot00000000000000defmodule Mix.Tasks.Archive do use Mix.Task @shortdoc "List all archives" @moduledoc """ Lists all installed archives. Archives are typically installed at `~/.mix/archives` although the installation path can be customize by setting the `MIX_ARCHIVES` environment variable. Since archives are specific to Elixir versions, it is expected from build tools to swap the `MIX_ARCHIVES` variable to different locations based on a particular Elixir installation. """ @spec run(OptionParser.argv) :: :ok def run(_) do archives = Mix.Local.archives_path |> Path.join("*.ez") |> Path.wildcard() if archives == [] do Mix.shell.info "No archives currently installed." else Enum.each archives, fn archive -> Mix.shell.info "* #{Path.basename(archive)}" end Mix.shell.info "Archives installed at: #{Mix.Local.archives_path}" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/archive.install.ex000066400000000000000000000073631254730255300246050ustar00rootroot00000000000000defmodule Mix.Tasks.Archive.Install do use Mix.Task @shortdoc "Install an archive locally" @moduledoc """ Install an archive locally. If no argument is supplied but there is an archive in the root (created with mix archive), then the archive will be installed locally. For example: mix do archive.build, archive.install The argument can be an archive located at some URL: mix archive.install http://example.com/foo.ez After installed, the tasks in the archive are available locally: mix some_task ## Command line options * `--system` - uses one of the system tools (curl, wget or powershell on Windows) to download the archive in case a URL is given * `--force` - forces installation without a shell prompt; primarily intended for automation in build systems like make """ @spec run(OptionParser.argv) :: boolean def run(argv) do {opts, argv, _} = OptionParser.parse(argv, switches: [force: :boolean, system: :boolean]) if src = List.first(argv) do %URI{path: path} = URI.parse(src) case Path.extname(path) do ".ez" -> install_archive(src, opts) _ -> Mix.raise "mix archive.install doesn't know how to install #{path}" end else src = Mix.Archive.name(Mix.Project.config[:app], Mix.Project.config[:version]) if File.exists?(src) do install_archive(src, opts) else Mix.raise "Expected PATH to be given, please use `mix archive.install PATH`" end end end defp install_archive(src, opts) do previous = previous_versions(src) if opts[:force] || should_install?(src, previous) do archive = Path.join(Mix.Local.archives_path(), basename(src)) check_file_exists(src, archive) opts = [force: true] ++ opts if Mix.Utils.copy_path!(src, archive, opts) do Mix.shell.info [:green, "* creating ", :reset, Path.relative_to_cwd(archive)] Mix.Local.check_archive_elixir_version archive unless archive in previous, do: remove_previous_versions(previous) end true = Code.append_path(Mix.Archive.ebin(archive)) else false end end defp basename(path) do %URI{path: path} = URI.parse(path) Path.basename(path) end defp should_install?(src, []) do Mix.shell.yes?("Are you sure you want to install archive #{src}?") end defp should_install?(_src, previous_files) do files = Enum.map_join(previous_files, ", ", &Path.basename/1) Mix.shell.yes?("Found existing archive(s): #{files}.\n" <> "Are you sure you want to replace them?") end defp check_file_exists(src, path) do # OTP keeps loaded archives open, this leads to unfortunate behaviour on # Windows when trying overwrite loaded archives. remove_previous_versions # completes successfully even though the file will be first removed after # the BEAM process is dead. Because of this we ask the user rerun the # command, which should complete successfully at that time if File.exists?(path) and match?({:win32, _}, :os.type) do Mix.raise "Unable to overwrite open archives on Windows. Please manually remove " <> "the existing archive at #{inspect path} and run this command again. In " <> "case re-running the command still does not work, please fetch the archive " <> "at #{inspect src} and manually copy it to #{inspect path}." end end defp previous_versions(src) do app = src |> Mix.Archive.dir |> String.split("-") |> List.first if app do Mix.Local.archive_files(app) else [] end end defp remove_previous_versions([]), do: :ok defp remove_previous_versions(previous), do: Enum.each(previous, &File.rm!/1) end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/archive.uninstall.ex000066400000000000000000000012631254730255300251410ustar00rootroot00000000000000defmodule Mix.Tasks.Archive.Uninstall do use Mix.Task @shortdoc "Uninstall archives" @moduledoc """ Uninstall local archives: mix archive.uninstall archive.ez """ @spec run(OptionParser.argv) :: :ok def run(argv) do {_, argv, _} = OptionParser.parse(argv) if name = List.first(argv) do path = Path.join(Mix.Local.archives_path, name) if File.regular?(path) do File.rm!(path) else Mix.shell.error "Could not find a local archive named #{inspect name}. "<> "Existing archives are:" Mix.Task.run "archive" end else Mix.raise "No archive was given to uninstall" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/clean.ex000066400000000000000000000025251254730255300225740ustar00rootroot00000000000000defmodule Mix.Tasks.Clean do use Mix.Task @shortdoc "Delete generated application files" @recursive true @moduledoc """ Delete generated application files. This command deletes all build artifacts for the current project. Dependencies' build files are cleaned if the `--deps` option is given. By default this task works across all environments, unless `--only` is given. """ @switches [deps: :boolean, only: :string] @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! loadpaths! {opts, _, _} = OptionParser.parse(args, switches: @switches) _ = for compiler <- Mix.Tasks.Compile.compilers(), module = Mix.Task.get("compile.#{compiler}"), function_exported?(module, :clean, 0), do: module.clean build = Mix.Project.build_path |> Path.dirname |> Path.join("#{opts[:only] || :*}") if opts[:deps] do build |> Path.wildcard |> Enum.each(&File.rm_rf/1) else build |> Path.join("lib/#{Mix.Project.config[:app]}") |> Path.wildcard |> Enum.each(&File.rm_rf/1) end end # Loadpaths without checks because compilers may be defined in deps. defp loadpaths! do Mix.Task.run "loadpaths", ["--no-elixir-version-check", "--no-deps-check"] Mix.Task.reenable "loadpaths" end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/cmd.ex000066400000000000000000000007501254730255300222530ustar00rootroot00000000000000defmodule Mix.Tasks.Cmd do use Mix.Task @shortdoc "Executes the given command" @recursive true @moduledoc """ Executes the given command. Useful in umbrella applications to execute a command on each child app: mix cmd echo pwd Aborts when the first command exits with status different than zero. """ @spec run(OptionParser.argv) :: :ok def run(args) do case Mix.shell.cmd(Enum.join(args, " ")) do 0 -> :ok s -> exit(s) end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.all.ex000066400000000000000000000011311254730255300237010ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.All do use Mix.Task @moduledoc false @recursive true # This is an internal task used by mix compile which # is meant to be recursive and be invoked for each child # project. def run(args) do Mix.Project.get! # Build the project structure so we can write down compiled files. Mix.Project.build_structure res = Enum.map(Mix.Tasks.Compile.compilers(), fn(compiler) -> Mix.Task.run("compile.#{compiler}", args) end) true = Code.prepend_path(Mix.Project.compile_path) if :ok in res, do: :ok, else: :noop end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.app.ex000066400000000000000000000157461254730255300237320ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.App do use Mix.Task @recursive true @moduledoc """ Writes an .app file. An `.app` file is a file containing Erlang terms that defines your application. Mix automatically generates this file based on your `mix.exs` configuration. You can learn more about OTP applications by seeing the documentation for the `Application` module. In order to generate the `.app` file, Mix expects your application to have both `:app` and `:version` keys. Furthermore, you can configure the generated application by defining an `application` function in your `mix.exs` with the following options: * `:applications` - all applications your application depends on at runtime. For example, if your application depends on Erlang's `:crypto`, it needs to be added to this list. Most of your dependencies must be added as well (unless they're a development or test dependency). Mix and other tools use this list in order to properly boot your application dependencies before starting the application itself. * `:registered` - the name of all registered processes in the application. If your application defines a local GenServer with name `MyServer`, it is recommended to add `MyServer` to this list. It is mostly useful to detect conflicts between applications that register the same names. * `:mod` - specify a module to invoke when the application is started, it must be in the format `{Mod, args}` where args is often an empty list. The module specified here must implement the callbacks defined by the `Application` module. * `:env` - default values for the application environment. The application environment is one of the most common ways to configure applications. Let's see an example `application` function: def application do [mod: {MyApp, []}, env: [default: :value], applications: [:crypto]] end Besides the options above, `.app` files also expects other options like `:modules` and `:vsn`, but those are automatically filled by Mix. ## Command line options * `--force` - forces compilation regardless of modification times """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean]) project = Mix.Project.get! config = Mix.Project.config app = Keyword.fetch!(config, :app) version = Keyword.fetch!(config, :version) validate_app(app) validate_version(version) path = Mix.Project.compile_path mods = modules_from(Path.wildcard("#{path}/*.beam")) |> Enum.sort target = Path.join(path, "#{app}.app") sources = Mix.Project.config_files if opts[:force] || Mix.Utils.stale?(sources, [target]) || modules_changed?(mods, target) do best_guess = [ vsn: to_char_list(version), modules: mods, applications: [] ] properties = if function_exported?(project, :application, 0) do Keyword.merge(best_guess, project.application) else best_guess end # Ensure we always prepend the standard application dependencies core_apps = [:kernel, :stdlib] ++ language_app(config) properties = Keyword.update!(properties, :applications, fn apps -> core_apps ++ apps end) properties = ensure_correct_properties(app, config, properties) contents = {:application, app, properties} Mix.Project.ensure_structure() File.write!(target, :io_lib.format("~p.", [contents])) Mix.shell.info "Generated #{app} app" :ok else :noop end end defp modules_changed?(mods, target) do case :file.consult(target) do {:ok, [{:application, _app, properties}]} -> properties[:modules] != mods _ -> false end end defp validate_app(app) when is_atom(app), do: :ok defp validate_app(_), do: Mix.raise("Expected :app to be an atom") defp validate_version(version) do unless is_binary(version) and match?({:ok, _}, Version.parse(version)) do Mix.raise("Expected :version to be a SemVer version") end end defp modules_from(beams) do Enum.map beams, &(&1 |> Path.basename |> Path.rootname(".beam") |> String.to_atom) end defp language_app(config) do case Keyword.fetch(config, :language) do {:ok, :elixir} -> [:elixir] {:ok, :erlang} -> [] :error -> [:elixir] end end defp ensure_correct_properties(app, config, properties) do properties |> Keyword.put_new(:description, to_char_list(config[:description] || app)) |> Keyword.put_new(:registered, []) |> validate_properties end defp validate_properties(properties) do Enum.each properties, fn {:description, value} -> unless is_list(value), do: invalid "Application description (:description) is not a character list (got #{inspect value})" {:id, value} -> unless is_list(value), do: invalid "Application id (:id) is not a character list (got #{inspect value} instead)" {:vsn, value} -> unless is_list(value), do: invalid "Application vsn (:vsn) is not a character list (got #{inspect value} instead)" {:maxT, value} -> unless value == :infinity or is_integer(value), do: invalid "Application maximum time (:maxT) is not an integer or :infinity (got #{inspect value} instead)" {:modules, value} -> unless is_list(value) and Enum.all?(value, &is_atom(&1)), do: invalid "Application modules (:modules) should be a list of atoms (got #{inspect value} instead)" {:registered, value} -> unless is_list(value) and Enum.all?(value, &is_atom(&1)), do: invalid "Application registered processes (:registered) should be a list of atoms (got #{inspect value} instead)" {:included_applications, value} -> unless is_list(value) and Enum.all?(value, &is_atom(&1)), do: invalid "Application included applications (:included_applications) should be a list of atoms (got #{inspect value} instead)" {:applications, value} -> unless is_list(value) and Enum.all?(value, &is_atom(&1)), do: invalid "Application dependencies (:applications) should be a list of atoms (got #{inspect value} instead)" {:env, value} -> unless Keyword.keyword?(value), do: invalid "Application dependencies (:env) should be a keyword list (got #{inspect value} instead)" {:start_phases, value} -> unless Keyword.keyword?(value), do: invalid "Application start phases (:start_phases) should be a keyword list (got #{inspect value} instead)" {:mod, []} -> :ok {:mod, {module, _args}} when is_atom(module) -> :ok {:mod, value} -> invalid "Application callback module (:mod) should be either [] or {module, start_args} (got #{inspect value} instead)" _ -> :ok end properties end defp invalid(message) do Mix.raise message end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.elixir.ex000066400000000000000000000063241254730255300244360ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.Elixir do use Mix.Task @recursive true @manifest ".compile.elixir" @moduledoc """ Compiles Elixir source files. Elixir is smart enough to recompile only files that changed and their dependencies. This means if `lib/a.ex` is invoking a function defined over `lib/b.ex`, whenever `lib/b.ex` changes, `lib/a.ex` is also recompiled. Note it is important to recompile a file dependencies because often there are compilation time dependencies between them. ## Command line options * `--force` - forces compilation regardless of modification times * `--docs` (`--no-docs`) - attach (or not) documentation to compiled modules * `--debug-info` (`--no-debug-info`) - attach (or not) debug info to compiled modules * `--ignore-module-conflict` - do not emit warnings if a module was previously defined * `--warnings-as-errors` - treat warnings as errors and return a non-zero exit code * `--elixirc-paths` - restrict the original elixirc paths to a subset of the ones specified. Can be given multiple times. ## Configuration * `:elixirc_paths` - directories to find source files. Defaults to `["lib"]`. * `:elixirc_options` - compilation options that apply to Elixir's compiler, they are: `:ignore_module_conflict`, `:docs` and `:debug_info`. By default, uses the same defaults as `elixirc` and they can always be overridden from the command line according to the options above. """ @switches [force: :boolean, docs: :boolean, warnings_as_errors: :boolean, ignore_module_conflict: :boolean, debug_info: :boolean, elixirc_paths: :keep] @doc """ Runs this task. """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do {opts, _, _} = OptionParser.parse(args, switches: @switches) project = Mix.Project.config dest = Mix.Project.compile_path(project) srcs = project[:elixirc_paths] skip = case Keyword.get_values(opts, :elixirc_paths) do [] -> [] ep -> srcs -- ep end manifest = manifest() configs = Mix.Project.config_files ++ Mix.Tasks.Compile.Erlang.manifests force = opts[:force] || local_deps_changed?(manifest) || Mix.Utils.stale?(configs, [manifest]) Mix.Compilers.Elixir.compile(manifest, srcs, skip, [:ex], dest, force, fn -> set_compiler_opts(project, opts, []) end) end @doc """ Returns Elixir manifests. """ def manifests, do: [manifest] defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest) @doc """ Cleans up compilation artifacts. """ def clean do Mix.Compilers.Elixir.clean(manifest()) end defp set_compiler_opts(project, opts, extra) do opts = Dict.take(opts, Code.available_compiler_options) opts = Keyword.merge(project[:elixirc_options] || [], opts) Code.compiler_options Keyword.merge(opts, extra) end defp local_deps_changed?(manifest) do manifest = Path.absname(manifest) Enum.any?(Mix.Dep.children([]), fn(dep) -> not dep.scm.fetchable? and Mix.Dep.in_dependency(dep, fn(_) -> files = Mix.Project.config_files ++ Mix.Tasks.Compile.manifests Mix.Utils.stale?(files, [manifest]) end) end) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.erlang.ex000066400000000000000000000117211254730255300244070ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.Erlang do use Mix.Task import Mix.Compilers.Erlang @recursive true @manifest ".compile.erlang" @moduledoc """ Compile Erlang source files. When this task runs, it will first check the modification times of all files to be compiled and if they haven't been changed since the last compilation, it will not compile them. If any of them have changed, it compiles everything. For this reason, the task touches your `:compile_path` directory and sets the modification time to the current time and date at the end of each compilation. You can force compilation regardless of modification times by passing the `--force` option. ## Command line options * `--force` - forces compilation regardless of modification times ## Configuration * `ERL_COMPILER_OPTIONS` - can be used to give default compile options. The value must be a valid Erlang term. If the value is a list, it will be used as is. If it is not a list, it will be put into a list. * `:erlc_paths` - directories to find source files. Defaults to `["src"]`. * `:erlc_include_path` - directory for adding include files. Defaults to `"include"`. * `:erlc_options` - compilation options that apply to Erlang's compiler. `:debug_info` is enabled by default. There are many available options here: http://www.erlang.org/doc/man/compile.html#file-2 """ @doc """ Runs this task. """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean]) project = Mix.Project.config source_paths = project[:erlc_paths] include_path = to_erl_file project[:erlc_include_path] compile_path = to_erl_file Mix.Project.compile_path(project) files = Mix.Utils.extract_files(source_paths, [:erl]) erlc_options = project[:erlc_options] || [] erlc_options = erlc_options ++ [{:outdir, compile_path}, {:i, include_path}, :report] erlc_options = Enum.map erlc_options, fn {kind, dir} when kind in [:i, :outdir] -> {kind, to_erl_file(dir)} opt -> opt end compile_path = Path.relative_to(compile_path, File.cwd!) tuples = files |> scan_sources(include_path, source_paths) |> sort_dependencies |> Enum.map(&annotate_target(&1, compile_path, opts[:force])) Mix.Compilers.Erlang.compile(manifest(), tuples, fn input, _output -> file = to_erl_file(Path.rootname(input, ".erl")) :compile.file(file, erlc_options) end) end @doc """ Returns Erlang manifests. """ def manifests, do: [manifest] defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest) @doc """ Cleans up compilation artifacts. """ def clean do Mix.Compilers.Erlang.clean(manifest()) end ## Internal helpers defp scan_sources(files, include_path, source_paths) do include_paths = [include_path | source_paths] Enum.reduce(files, [], &scan_source(&2, &1, include_paths)) |> Enum.reverse end defp scan_source(acc, file, include_paths) do erl_file = %{file: file, module: module_from_artifact(file), behaviours: [], compile: [], includes: [], invalid: false} case :epp.parse_file(to_erl_file(file), include_paths, []) do {:ok, forms} -> [List.foldl(tl(forms), erl_file, &do_form(file, &1, &2)) | acc] {:error, _error} -> acc end end defp do_form(file, form, erl) do case form do {:attribute, _, :file, {include_file, _}} when file != include_file -> if File.regular?(include_file) do %{erl | includes: [include_file|erl.includes]} else erl end {:attribute, _, :behaviour, behaviour} -> %{erl | behaviours: [behaviour|erl.behaviours]} {:attribute, _, :compile, value} -> %{erl | compile: [value|erl.compile]} _ -> erl end end defp sort_dependencies(erls) do graph = :digraph.new _ = for erl <- erls do :digraph.add_vertex(graph, erl.module, erl) end _ = for erl <- erls do _ = for b <- erl.behaviours, do: :digraph.add_edge(graph, b, erl.module) _ = for c <- erl.compile do case c do {:parse_transform, transform} -> :digraph.add_edge(graph, transform, erl.module) _ -> :ok end end :ok end result = case :digraph_utils.topsort(graph) do false -> erls mods -> for m <- mods, do: elem(:digraph.vertex(graph, m), 1) end :digraph.delete(graph) result end defp annotate_target(erl, compile_path, force) do beam = Path.join(compile_path, "#{erl.module}#{:code.objfile_extension}") if force || Mix.Utils.stale?([erl.file|erl.includes], [beam]) do {:stale, erl.file, beam} else {:ok, erl.file, beam} end end defp module_from_artifact(artifact) do artifact |> Path.basename |> Path.rootname |> String.to_atom end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.ex000066400000000000000000000055101254730255300231370ustar00rootroot00000000000000defmodule Mix.Tasks.Compile do use Mix.Task @shortdoc "Compile source files" @moduledoc """ A meta task that compiles source files. It simply runs the compilers registered in your project. At the end of compilation it ensures load paths are set. ## Configuration * `:compilers` - compilers to run, defaults to: `[:yeec, :leex, :erlang, :elixir, :app]` * `:consolidate_protocols` - when true, runs protocol consolidation via the `compile.protocols` task * `:build_embedded` - when true, activates protocol consolidation and does not generate symlinks in builds ## Command line options * `--list` - list all enabled compilers * `--no-deps-check` - skip checking of dependencies * `--force` - force compilation """ @spec run(OptionParser.argv) :: :ok | :noop def run(["--list"]) do loadpaths! _ = Mix.Task.load_all shell = Mix.shell modules = Mix.Task.all_modules docs = for module <- modules, task = Mix.Task.task_name(module), match?("compile." <> _, task), doc = Mix.Task.moduledoc(module) do {task, first_line(doc)} end max = Enum.reduce docs, 0, fn({task, _}, acc) -> max(byte_size(task), acc) end sorted = Enum.sort(docs) Enum.each sorted, fn({task, doc}) -> shell.info format('mix ~-#{max}s # ~ts', [task, doc]) end compilers = compilers() ++ if(consolidate_protocols?(), do: [:protocols], else: []) shell.info "\nEnabled compilers: #{Enum.join compilers, ", "}" :ok end def run(args) do Mix.Project.get! Mix.Task.run "loadpaths", args res = Mix.Task.run "compile.all", args res = if :ok in List.wrap(res), do: :ok, else: :noop if res == :ok && consolidate_protocols?() do Mix.Task.run "compile.protocols", args end res end # Loadpaths without checks because compilers may be defined in deps. defp loadpaths! do Mix.Task.run "loadpaths", ["--no-elixir-version-check", "--no-deps-check"] Mix.Task.reenable "loadpaths" end defp consolidate_protocols? do config = Mix.Project.config Keyword.get(config, :consolidate_protocols, config[:build_embedded]) end @doc """ Returns all compilers. """ def compilers do Mix.Project.config[:compilers] || Mix.compilers end @doc """ Returns manifests for all compilers. """ def manifests do Enum.flat_map(compilers(), fn(compiler) -> module = Mix.Task.get!("compile.#{compiler}") if function_exported?(module, :manifests, 0) do module.manifests else [] end end) end defp format(expression, args) do :io_lib.format(expression, args) |> IO.iodata_to_binary end defp first_line(doc) do String.split(doc, "\n", parts: 2) |> hd |> String.strip |> String.rstrip(?.) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.leex.ex000066400000000000000000000032601254730255300240730ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.Leex do use Mix.Task alias Mix.Compilers.Erlang @recursive true @manifest ".compile.leex" @moduledoc """ Compile Leex source files. When this task runs, it will check the modification time of every file, and if it has changed, the file will be compiled. Files will be compiled in the same source directory with a .erl extension. You can force compilation regardless of modification times by passing the `--force` option. ## Command line options * `--force` - forces compilation regardless of modification times ## Configuration * `:erlc_paths` - directories to find source files. Defaults to `["src"]`. * `:leex_options` - compilation options that apply to Leex's compiler. There are many available options here: http://www.erlang.org/doc/man/leex.html#file-2. """ @doc """ Runs this task. """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean]) project = Mix.Project.config source_paths = project[:erlc_paths] mappings = Enum.zip(source_paths, source_paths) options = project[:leex_options] || [] Erlang.compile(manifest(), mappings, :xrl, :erl, opts[:force], fn input, output -> options = options ++ [scannerfile: Erlang.to_erl_file(output), report: true] :leex.file(Erlang.to_erl_file(input), options) end) end @doc """ Returns Leex manifests. """ def manifests, do: [manifest] defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest) @doc """ Cleans up compilation artifacts. """ def clean do Erlang.clean(manifest()) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.protocols.ex000066400000000000000000000044551254730255300251710ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.Protocols do use Mix.Task @moduledoc ~S""" Consolidates all protocols in all paths. This task is automatically invoked whenever the project enables `:consolidate_protocols` or `:build_embedded` in its configuration. ## Consolidation Protocol consolidation is useful in production when no dynamic code loading will happen, effectively optimizing protocol dispatches by not accounting for code loading. This task consolidates all protocols in the code path and output the new binary files to the given directory (defaults to "_build/MIX_ENV/consolidated"). In case you are manually compiling protocols or building releases, you need to take the generated protocols into account. This can be done with: $ elixir -pa _build/MIX_ENV/consolidated -S mix run You can verify a protocol is consolidated by checking its attributes: $ iex -pa _build/MIX_ENV/consolidated -S mix run iex> Protocol.consolidated?(Enumerable) true """ @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Task.run "compile", args {opts, _, _} = OptionParser.parse(args, switches: [output: :string], aliases: [o: :output]) paths = filter_otp(:code.get_path, :code.lib_dir) paths |> Protocol.extract_protocols |> consolidate(paths, opts[:output] || default_path()) :ok end @doc false def default_path, do: Path.join(Mix.Project.build_path, "consolidated") defp filter_otp(paths, otp) do Enum.filter(paths, &(not :lists.prefix(&1, otp))) end defp consolidate(protocols, paths, output) do File.mkdir_p!(output) _ = for protocol <- protocols do impls = Protocol.extract_impls(protocol, paths) maybe_reload(protocol) {:ok, binary} = Protocol.consolidate(protocol, impls) File.write!(Path.join(output, "#{protocol}.beam"), binary) Mix.shell.info "Consolidated #{inspect protocol}" end relative = Path.relative_to_cwd(output) Mix.shell.info "Consolidated protocols written to #{relative}" end defp maybe_reload(module) do case :code.which(module) do atom when is_atom(atom) -> # Module is likely in memory, we purge as an attempt to reload it :code.purge(module) :code.delete(module) :ok _file -> :ok end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/compile.yecc.ex000066400000000000000000000032651254730255300240660ustar00rootroot00000000000000defmodule Mix.Tasks.Compile.Yecc do use Mix.Task alias Mix.Compilers.Erlang @recursive true @manifest ".compile.yecc" @moduledoc """ Compile Yecc source files. When this task runs, it will check the modification time of every file, and if it has changed, the file will be compiled. Files will be compiled in the same source directory with a .erl extension. You can force compilation regardless of modification times by passing the `--force` option. ## Command line options * `--force` - forces compilation regardless of modification times ## Configuration * `:erlc_paths` - directories to find source files. Defaults to `["src"]`. * `:yecc_options` - compilation options that apply to Yecc's compiler. There are many other available options here: http://www.erlang.org/doc/man/yecc.html#file-1. """ @doc """ Runs this task. """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean]) project = Mix.Project.config source_paths = project[:erlc_paths] mappings = Enum.zip(source_paths, source_paths) options = project[:yecc_options] || [] Erlang.compile(manifest(), mappings, :yrl, :erl, opts[:force], fn input, output -> options = options ++ [parserfile: Erlang.to_erl_file(output), report: true] :yecc.file(Erlang.to_erl_file(input), options) end) end @doc """ Returns Yecc manifests. """ def manifests, do: [manifest] defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest) @doc """ Cleans up compilation artifacts. """ def clean do Erlang.clean(manifest()) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.check.ex000066400000000000000000000067671254730255300235350ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Check do use Mix.Task import Mix.Dep, only: [loaded: 1, loaded_by_name: 2, format_dep: 1, format_status: 1, check_lock: 2, ok?: 1] @moduledoc """ Checks if all dependencies are valid and if not, abort. Prints the invalid dependencies' status before aborting. This task is not shown in `mix help` but it is part of the `mix` public API and can be depended on. ## Command line options * `--no-compile` - do not compile dependencies """ @spec run(OptionParser.argv) :: :ok def run(args) do lock = Mix.Dep.Lock.read all = Enum.map(loaded(env: Mix.env), &check_lock(&1, lock)) _ = prune_deps(all) {not_ok, compile} = partition_deps(all, [], []) cond do not_ok != [] -> show_not_ok(not_ok) compile == [] or "--no-compile" in args -> :ok true -> Mix.Tasks.Deps.Compile.compile(compile) show_not_ok compile |> Enum.map(& &1.app) |> loaded_by_name(env: Mix.env) |> Enum.filter(&(not ok?(&1))) end end defp partition_deps([dep|deps], not_ok, compile) do cond do from_umbrella?(dep) -> partition_deps(deps, not_ok, compile) compilable?(dep) -> partition_deps(deps, not_ok, [dep|compile]) ok?(dep) and local?(dep) -> partition_deps(deps, not_ok, [dep|compile]) ok?(dep) -> partition_deps(deps, not_ok, compile) true -> partition_deps(deps, [dep|not_ok], compile) end end defp partition_deps([], not_ok, compile) do {Enum.reverse(not_ok), Enum.reverse(compile)} end # Those are compiled by umbrella. defp from_umbrella?(dep) do dep.opts[:from_umbrella] end # Every local dependency (i.e. that are not fetchable) # are automatically recompiled if they are ok. defp local?(dep) do not dep.scm.fetchable? end # Can the dependency be compiled automatically without user intervention? defp compilable?(%Mix.Dep{status: {:elixirlock, _}}), do: true defp compilable?(%Mix.Dep{status: {:noappfile, _}}), do: true defp compilable?(%Mix.Dep{status: :compile}), do: true defp compilable?(%Mix.Dep{}), do: false # If the build is per environment, we should be able to look # at all dependencies and remove the builds that no longer # have a dependency defined for them. # # Notice we require the build_path to be nil. If the build_path # is not nil, it means it was set by a parent application and # the parent application should be the one to do the pruning. defp prune_deps(all) do config = Mix.Project.config if is_nil(config[:build_path]) && config[:build_per_environment] do paths = Mix.Project.build_path(config) |> Path.join("lib/*/ebin") |> Path.wildcard |> List.delete(config[:app] && Mix.Project.compile_path(config)) to_prune = Enum.reduce(all, paths, &(&2 -- Mix.Dep.load_paths(&1))) Enum.map(to_prune, fn path -> # Path cannot be in code path when deleting _ = Code.delete_path(path) File.rm_rf!(path |> Path.dirname) end) else [] end end defp show_not_ok([]) do :ok end defp show_not_ok(deps) do shell = Mix.shell shell.error "Unchecked dependencies for environment #{Mix.env}:" Enum.each deps, fn(dep) -> shell.error "* #{format_dep(dep)}" shell.error " #{format_status dep}" end Mix.raise "Can't continue due to errors on dependencies" end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.clean.ex000066400000000000000000000047401254730255300235270ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Clean do use Mix.Task @shortdoc "Remove the given dependencies' files" @moduledoc """ Remove the given dependencies' files, including build artifacts and fetched sources. Since this is a destructive action, cleaning of dependencies can only happen by passing arguments/options: * `dep1, dep2` - the name of dependencies to be removed * `--all` - removes all dependencies * `--unused` - removes only unused dependencies (no longer mentioned in the `mix.exs` file) * `--unlock` - also unlock the removed dependencies By default this task works across all environments, unless `--only` is given. """ @switches [unlock: :boolean, all: :boolean, only: :string, unused: :boolean] @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! {opts, apps, _} = OptionParser.parse(args, switches: @switches) build = Mix.Project.build_path |> Path.dirname |> Path.join("#{opts[:only] || :*}/lib") deps = Mix.Project.deps_path cond do opts[:all] -> checked_deps(build, deps) |> do_clean(build, deps) opts[:unused] -> checked_deps(build, deps) |> filter_loaded(opts) |> do_clean(build, deps) apps != [] -> do_clean(apps, build, deps) true -> Mix.raise "mix deps.clean expects dependencies as arguments or " <> "a flag indicating which dependencies to clean. " <> "The --all option will clean all dependencies while " <> "the --unused option cleans unused dependencies." end if opts[:unlock] do Mix.Task.run "deps.unlock", args else :ok end end defp checked_deps(build, deps) do for root <- [deps, build], path <- Path.wildcard(Path.join(root, "*")), File.dir?(path) do Path.basename(path) end |> Enum.uniq() |> List.delete(to_string(Mix.Project.config[:app])) end defp filter_loaded(apps, opts) do load_opts = if only = opts[:only], do: [env: :"#{only}"], else: [] load_deps = Mix.Dep.loaded(load_opts) |> Enum.map(&Atom.to_string(&1.app)) Enum.reject(apps, &(&1 in load_deps)) end defp do_clean(apps, build, deps) do shell = Mix.shell Enum.each apps, fn(app) -> shell.info "* Cleaning #{app}" build |> Path.join(to_string(app)) |> Path.wildcard |> Enum.each(&File.rm_rf!/1) deps |> Path.join(to_string(app)) |> File.rm_rf! end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.compile.ex000066400000000000000000000131621254730255300240730ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Compile do use Mix.Task @shortdoc "Compile dependencies" @moduledoc """ Compile dependencies. By default, compile all dependencies. A list of dependencies can be given to force the compilation of specific dependencies. This task attempts to detect if the project contains one of the following files and act accordingly: * `mix.exs` - invokes `mix compile` * `rebar.config` - invokes `rebar compile` * `Makefile.win` - invokes `nmake /F Makefile.win` (only on Windows) * `Makefile` - invokes `make` (except on Windows) The compilation can be customized by passing a `compile` option in the dependency: {:some_dependency, "0.1.0", compile: "command to compile"} """ import Mix.Dep, only: [loaded: 1, available?: 1, loaded_by_name: 2, format_dep: 1, make?: 1, mix?: 1, rebar?: 1] @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! case OptionParser.parse(args) do {_, [], _} -> # Because this command is invoked explicitly with # deps.compile, we simply try to compile any available # dependency. compile(Enum.filter(loaded(env: Mix.env), &available?/1)) {_, tail, _} -> compile(loaded_by_name(tail, env: Mix.env)) end end @doc false def compile(deps) do shell = Mix.shell config = Mix.Project.deps_config Mix.Task.run "deps.loadpaths" compiled = Enum.map(deps, fn %Mix.Dep{app: app, status: status, opts: opts, scm: scm} = dep -> check_unavailable!(app, status) compiled = cond do not is_nil(opts[:compile]) -> do_compile dep mix?(dep) -> do_mix dep rebar?(dep) -> do_rebar dep, config make?(dep) -> do_make dep true -> shell.error "Could not compile #{app}, no mix.exs, rebar.config or Makefile " <> "(pass :compile as an option to customize compilation, set it to false to do nothing)" end unless mix?(dep), do: build_structure(dep, config) touch_fetchable(scm, opts[:build]) compiled end) if Enum.any?(compiled), do: Mix.Dep.Lock.touch, else: :ok end defp touch_fetchable(scm, path) do if scm.fetchable? do File.mkdir_p!(path) File.touch!(Path.join(path, ".compile.fetch")) end end defp check_unavailable!(app, {:unavailable, _}) do Mix.raise "Cannot compile dependency #{app} because " <> "it isn't available, run `mix deps.get` first" end defp check_unavailable!(_, _) do :ok end defp do_mix(dep) do Mix.Dep.in_dependency dep, fn _ -> if req = old_elixir_req(Mix.Project.config) do Mix.shell.error "warning: the dependency #{dep.app} requires Elixir #{inspect req} " <> "but you are running on v#{System.version}" end try do res = Mix.Task.run("compile", ["--no-deps", "--no-elixir-version-check"]) :ok in List.wrap(res) catch kind, reason -> stacktrace = System.stacktrace app = dep.app Mix.shell.error "could not compile dependency #{app}, mix compile failed. " <> "You can recompile this dependency with `mix deps.compile #{app}` or " <> "update it with `mix deps.update #{app}`" :erlang.raise(kind, reason, stacktrace) end end end defp do_rebar(%Mix.Dep{app: app} = dep, config) do lib_path = Path.join(config[:build_path], "lib") do_command dep, rebar_cmd(app), false, "compile skip_deps=true deps_dir=#{inspect lib_path}" end defp rebar_cmd(app) do Mix.Rebar.rebar_cmd || handle_rebar_not_found(app) end defp handle_rebar_not_found(app) do shell = Mix.shell shell.info "Could not find rebar, which is needed to build dependency #{inspect app}" shell.info "I can install a local copy which is just used by mix" unless shell.yes?("Shall I install rebar?") do Mix.raise "Could not find rebar to compile " <> "dependency #{app}, please ensure rebar is available" end (Mix.Tasks.Local.Rebar.run([]) && Mix.Rebar.local_rebar_cmd) || Mix.raise "rebar installation failed" end defp do_make(dep) do command = if match?({:win32, _}, :os.type) and File.regular?("Makefile.win") do "nmake /F Makefile.win" else "make" end do_command(dep, command, true) end defp do_compile(%Mix.Dep{opts: opts} = dep) do if command = opts[:compile] do do_command(dep, command, true) else false end end defp do_command(%Mix.Dep{app: app} = dep, command, print_app?, extra \\ "") do Mix.Dep.in_dependency dep, fn _ -> if Mix.shell.cmd("#{command} #{extra}", print_app: print_app?) != 0 do Mix.raise "Could not compile dependency #{app}, #{command} command failed. " <> "If you want to recompile this dependency, please run: mix deps.compile #{app}" end end true end defp build_structure(%Mix.Dep{opts: opts} = dep, config) do build_path = Path.dirname(opts[:build]) Enum.each Mix.Dep.source_paths(dep), fn source -> app = Path.join(build_path, Path.basename(source)) build_structure(source, app, config) Code.prepend_path(Path.join(app, "ebin")) end end defp build_structure(dest, build, config) do File.cd! dest, fn -> config = Keyword.put(config, :app_path, build) Mix.Project.build_structure(config, symlink_ebin: true) end end defp old_elixir_req(config) do req = config[:elixir] if req && not Version.match?(System.version, req) do req end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.ex000066400000000000000000000070161254730255300224450ustar00rootroot00000000000000defmodule Mix.Tasks.Deps do use Mix.Task import Mix.Dep, only: [loaded: 1, format_dep: 1, format_status: 1, check_lock: 2] @shortdoc "List dependencies and their status" @moduledoc ~S""" List all dependencies and their status. Dependencies must be specified in the `mix.exs` file in one of the following formats: {app, requirement} {app, opts} {app, requirement, opts} Where: * app is an atom * requirement is a version requirement or a regular expression * opts is a keyword list of options By default, dependencies are fetched using the [Hex package manager](https://hex.pm/): {:plug, ">= 0.4.0"} By specifying such dependencies, Mix will automatically install Hex (if it wasn't previously installed and download a package suitable to your project). Mix also supports git and path dependencies: {:foobar, git: "https://github.com/elixir-lang/foobar.git", tag: "0.1"} {:foobar, path: "path/to/foobar"} And also in umbrella dependencies: {:myapp, in_umbrella: true} Path and in umbrella dependencies are automatically recompiled by the parent project whenever they change. While fetchable dependencies like git are recompiled only when fetched/updated. The dependencies versions are expected to follow Semantic Versioning and the requirements must be specified as defined in the `Version` module. Below we provide a more detailed look into the available options. ## Mix options * `:app` - when set to `false`, does not read the app file for this dependency * `:env` - the environment to run the dependency on, defaults to :prod * `:compile` - a command to compile the dependency, defaults to a mix, rebar or make command * `:optional` - the dependency is optional and used only to specify requirements * `:only` - the dependency will belong only to the given environments, useful when declaring dev- or test-only dependencies * `:override` - if set to `true` the dependency will override any other definitions of itself by other dependencies ## Git options (`:git`) * `:git` - the git repository URI * `:github` - a shortcut for specifying git repos from github, uses `git:` * `:ref` - the reference to checkout (may be a branch, a commit sha or a tag) * `:branch` - the git branch to checkout * `:tag` - the git tag to checkout * `:submodules` - when ` true`, initialize submodules for the repo ## Path options (`:path`) * `:path` - the path for the dependency * `:in_umbrella` - when `true`, sets a path dependency pointing to "../#{app}", sharing the same environment as the current application ## mix deps task This task lists all dependencies in the following format: APP VERSION (SCM) [locked at REF] STATUS It supports the following options: * `--all` - check all dependencies, regardless of specified environment """ @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! {opts, _, _} = OptionParser.parse(args) if opts[:all] do loaded_opts = [] else loaded_opts = [env: Mix.env] end shell = Mix.shell lock = Mix.Dep.Lock.read Enum.each loaded(loaded_opts), fn %Mix.Dep{scm: scm} = dep -> dep = check_lock(dep, lock) shell.info "* #{format_dep(dep)}" if formatted = scm.format_lock(dep.opts) do shell.info " locked at #{formatted}" end shell.info " #{format_status dep}" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.get.ex000066400000000000000000000015251254730255300232220ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Get do use Mix.Task @shortdoc "Get all out of date dependencies" @moduledoc """ Get all out of date dependencies, i.e. dependencies that are not available or have an invalid lock. ## Command line options * `--quiet` - do not output verbose messages * `--only` - only fetch dependencies for given environment """ @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! {opts, _, _} = OptionParser.parse(args, switches: [quiet: :boolean, only: :string]) # Fetch all deps by default unless --only is given fetch_opts = if only = opts[:only], do: [env: :"#{only}"], else: [] apps = Mix.Dep.Fetcher.all(%{}, Mix.Dep.Lock.read, fetch_opts) if apps == [] && !opts[:quiet] do Mix.shell.info "All dependencies up to date" else :ok end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.loadpaths.ex000066400000000000000000000006331254730255300244210ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Loadpaths do use Mix.Task @moduledoc """ Loads the available dependencies paths. """ @spec run(OptionParser.argv) :: :ok def run(_) do config = Mix.Project.config Mix.Project.build_path(config) |> Path.join("lib/*/ebin") |> Path.wildcard |> List.delete(config[:app] && Mix.Project.compile_path(config)) |> Enum.each(&Code.prepend_path/1) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.unlock.ex000066400000000000000000000026501254730255300237360ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Unlock do use Mix.Task @shortdoc "Unlock the given dependencies" @moduledoc """ Unlock the given dependencies. Since this is a destructive action, unlocking of dependencies can only happen by passing arguments/options: * `dep1 dep2` - the name of dependencies to be unlocked * `--all` - unlocks all dependencies * `--unused` - unlocks only unused dependencies (no longer mentioned in the `mix.exs` file) """ @switches [all: :boolean, unused: :boolean] @spec run(OptionParser.argv) :: :ok def run(args) do Mix.Project.get! {opts, apps, _} = OptionParser.parse(args, switches: @switches) cond do opts[:all] -> Mix.Dep.Lock.write(%{}) opts[:unused] -> apps = Mix.Dep.loaded([]) |> Enum.map(& &1.app) Mix.Dep.Lock.read() |> Map.take(apps) |> Mix.Dep.Lock.write() apps != [] -> lock = Enum.reduce apps, Mix.Dep.Lock.read, fn(app_str, lock) -> app = String.to_atom(app_str) if Map.has_key?(lock, app) do Map.delete(lock, app) else Mix.shell.error "warning: #{app} dependency is not locked" lock end end Mix.Dep.Lock.write(lock) true -> Mix.raise "mix deps.unlock expects dependencies as arguments or " <> "the --all option to unlock all dependencies" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/deps.update.ex000066400000000000000000000025021254730255300237210ustar00rootroot00000000000000defmodule Mix.Tasks.Deps.Update do use Mix.Task @shortdoc "Update the given dependencies" @moduledoc """ Update the given dependencies. Since this is a destructive action, update of all dependencies can only happen by passing the `--all` command line option. All dependencies are automatically recompiled after update. ## Command line options * `--all` - update all dependencies * `--only` - only fetch dependencies for given environment """ @spec run(OptionParser.argv) :: [atom] def run(args) do Mix.Project.get! {opts, rest, _} = OptionParser.parse(args, switches: [all: :boolean, only: :string]) # Fetch all deps by default unless --only is given fetch_opts = if only = opts[:only], do: [env: :"#{only}"], else: [] cond do opts[:all] -> Mix.Dep.Fetcher.all(Mix.Dep.Lock.read, %{}, fetch_opts) rest != [] -> {old, new} = Dict.split(Mix.Dep.Lock.read, to_app_names(rest)) Mix.Dep.Fetcher.by_name(rest, old, new, fetch_opts) true -> Mix.raise "mix deps.update expects dependencies as arguments or " <> "the --all option to update all dependencies" end end defp to_app_names(given) do Enum.map given, fn(app) -> if is_binary(app), do: String.to_atom(app), else: app end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/do.ex000066400000000000000000000017601254730255300221140ustar00rootroot00000000000000defmodule Mix.Tasks.Do do use Mix.Task @shortdoc "Executes the tasks separated by comma" @moduledoc """ Executes the tasks separated by comma. ## Examples The example below prints the available compilers and then the list of dependencies. mix do compile --list, deps """ @spec run(OptionParser.argv) :: :ok def run(args) do Enum.each gather_commands(args), fn [task|args] -> Mix.Task.run task, args [] -> Mix.raise "No expression between commas" end end defp gather_commands(args) do gather_commands args, [], [] end defp gather_commands([h|t], current, acc) when binary_part(h, byte_size(h), -1) == "," do part = binary_part(h, 0, byte_size(h) - 1) current = Enum.reverse([part|current]) gather_commands t, [], [current|acc] end defp gather_commands([h|t], current, acc) do gather_commands t, [h|current], acc end defp gather_commands([], current, acc) do Enum.reverse [Enum.reverse(current)|acc] end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/escript.build.ex000066400000000000000000000227611254730255300242650ustar00rootroot00000000000000defmodule Mix.Tasks.Escript.Build do use Mix.Task use Bitwise, only_operators: true @shortdoc "Builds an escript for the project" @recursive true @moduledoc ~S""" Builds an escript for the project. An escript is an executable that can be invoked from the command line. An escript can run on any machine that has Erlang installed and by default does not require Elixir to be installed, as Elixir is embedded as part of the escript. This task guarantees the project and its dependencies are compiled and packages them inside an escript. > Note: escripts do not support projects and dependencies > that need to store or read artifacts from the priv directory. ## Command line options * `--force` - forces compilation regardless of modification times * `--no-compile` - skips compilation to .beam files ## Configuration The following option must be specified in your `mix.exs` under `:escript` key: * `:main_module` - the module to be invoked once the escript starts. The module must contain a function named `main/1` that will receive the command line arguments as binaries. The remaining options can be specified to further customize the escript: * `:name` - the name of the generated escript. Defaults to app name. * `:path` - the path to write the escript to. Defaults to app name. * `:app` - the app to start with the escript. Defaults to app name. Set it to `nil` if no application should be started. * `:embed_elixir` - if `true` embed elixir and its children apps (`ex_unit`, `mix`, etc.) mentioned in the `:applications` list inside the `application` function in `mix.exs`. Defaults to `true` for Elixir projects, `false` for Erlang projects. Note: if you set this to `false` for an Elixir project, you will have to add paths to Elixir's `ebin` directories to `ERL_LIBS` environment variable when running the resulting escript, in order for the code loader to be able to find `:elixir` application and its children applications (if they are used). * `:shebang` - shebang interpreter directive used to execute the escript. Defaults to `"#! /usr/bin/env escript\n"`. * `:comment` - comment line to follow shebang directive in the escript. Defaults to `""`. * `:emu_args` - emulator arguments to embed in the escript file. Defaults to `""`. There is one project-level option that affects how the escript is generated: * `language: :elixir | :erlang` - set it to `:erlang` for Erlang projects managed by mix. Doing so will ensure Elixir is not embedded by default. Your app will still be started as part of escript loading, with the config used during build. ## Example defmodule MyApp.Mixfile do def project do [app: :myapp, version: "0.0.1", escript: escript] end def escript do [main_module: MyApp.CLI] end end """ @spec run(OptionParser.argv) :: :ok | :noop def run(args) do Mix.Project.get! {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean, compile: :boolean]) if Keyword.get(opts, :compile, true) do Mix.Task.run :compile, args end project = Mix.Project.config language = Keyword.get(project, :language, :elixir) escriptize(project, language, opts[:force]) end defp escriptize(project, language, force) do escript_opts = project[:escript] || [] script_name = to_string(escript_opts[:name] || project[:app]) filename = escript_opts[:path] || script_name main = escript_opts[:main_module] app = Keyword.get(escript_opts, :app, project[:app]) files = project_files() escript_mod = String.to_atom(Atom.to_string(app) <> "_escript") cond do !script_name -> Mix.raise "Could not generate escript, no name given, " <> "set :name escript option or :app in the project settings" !main or !Code.ensure_loaded?(main)-> Mix.raise "Could not generate escript, please set :main_module " <> "in your project configuration (under `:escript` option) to a module that implements main/1" force || Mix.Utils.stale?(files, [filename]) -> beam_paths = [files, deps_files(), core_files(escript_opts, language)] |> Stream.concat |> prepare_beam_paths if Keyword.get(project, :consolidate_protocols, project[:build_embedded]) do beam_paths = Path.wildcard(consolidated_path <> "/*") |> prepare_beam_paths(beam_paths) end tuples = gen_main(escript_mod, main, app, language) ++ read_beams(beam_paths) case :zip.create 'mem', tuples, [:memory] do {:ok, {'mem', zip}} -> shebang = escript_opts[:shebang] || "#! /usr/bin/env escript\n" comment = build_comment(escript_opts[:comment]) emu_args = build_emu_args(escript_opts[:emu_args], escript_mod) script = IO.iodata_to_binary([shebang, comment, emu_args, zip]) File.mkdir_p!(Path.dirname(filename)) File.write!(filename, script) set_perms(filename) {:error, error} -> Mix.raise "Error creating escript: #{error}" end Mix.shell.info "Generated escript #{filename} with MIX_ENV=#{Mix.env}" :ok true -> :noop end end defp project_files() do get_files(Mix.Project.app_path) end defp get_files(app) do Path.wildcard("#{app}/ebin/*.{app,beam}") ++ (Path.wildcard("#{app}/priv/**/*") |> Enum.filter(&File.regular?/1)) end defp set_perms(filename) do stat = File.stat!(filename) :ok = File.chmod(filename, stat.mode ||| 0o111) end defp deps_files() do deps = Mix.Dep.loaded(env: Mix.env) || [] Enum.flat_map(deps, fn dep -> get_files(dep.opts[:build]) end) end defp core_files(escript_opts, language) do if Keyword.get(escript_opts, :embed_elixir, language == :elixir) do Enum.flat_map [:elixir|extra_apps()], &app_files/1 else [] end end defp extra_apps() do mod = Mix.Project.get! extra_apps = if function_exported?(mod, :application, 0) do mod.application[:applications] end Enum.filter(extra_apps || [], &(&1 in [:eex, :ex_unit, :mix, :iex, :logger])) end defp app_files(app) do case :code.where_is_file('#{app}.app') do :non_existing -> Mix.raise "Could not find application #{app}" file -> get_files(Path.dirname(Path.dirname(file))) end end defp prepare_beam_paths(paths, dict \\ HashDict.new) do paths |> Enum.map(&{Path.basename(&1), &1}) |> Enum.into(dict) end defp read_beams(items) do items |> Enum.map(fn {basename, beam_path} -> {String.to_char_list(basename), File.read!(beam_path)} end) end defp consolidated_path, do: Mix.Tasks.Compile.Protocols.default_path defp build_comment(user_comment) do "%% #{user_comment}\n" end defp build_emu_args(user_args, escript_mod) do "%%! -escript main #{escript_mod} #{user_args}\n" end defp gen_main(name, module, app, language) do config = if File.regular?("config/config.exs") do Macro.escape Mix.Config.read!("config/config.exs") else [] end module_body = quote do @module unquote(module) @config unquote(config) @app unquote(app) @spec main(OptionParser.argv) :: any def main(args) do unquote(main_body_for(language)) end defp load_config(config) do :lists.foreach(fn {app, kw} -> :lists.foreach(fn {k, v} -> :application.set_env(app, k, v, persistent: true) end, kw) end, config) :ok end defp start_app(nil) do :ok end defp start_app(app) do case :application.ensure_all_started(app) do {:ok, _} -> :ok {:error, {app, reason}} -> formatted_error = case :code.ensure_loaded(Application) do {:module, Application} -> Application.format_error(reason) {:error, _} -> :io_lib.format('~p', [reason]) end io_error ["Could not start application ", :erlang.atom_to_binary(app, :utf8), ": ", formatted_error, ?\n] :erlang.halt(1) end end defp io_error(message) do :io.put_chars(:standard_error, message) end end {:module, ^name, binary, _} = Module.create(name, module_body, Macro.Env.location(__ENV__)) [{'#{name}.beam', binary}] end defp main_body_for(:elixir) do quote do erl_version = :erlang.system_info(:otp_release) case :string.to_integer(erl_version) do {num, _} when num >= 17 -> nil _ -> io_error ["Incompatible Erlang/OTP release: ", erl_version, ".\nThis escript requires at least Erlang/OTP 17.0.\n"] :erlang.halt(1) end case :application.ensure_all_started(:elixir) do {:ok, _} -> load_config(@config) start_app(@app) args = Enum.map(args, &List.to_string(&1)) Kernel.CLI.run fn _ -> @module.main(args) end, true error -> io_error ["Failed to start Elixir.\n", :io_lib.format('error: ~p~n', [error])] :erlang.halt(1) end end end defp main_body_for(:erlang) do quote do load_config(@config) start_app(@app) @module.main(args) end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/help.ex000066400000000000000000000107201254730255300224360ustar00rootroot00000000000000defmodule Mix.Tasks.Help do use Mix.Task @shortdoc "Print help information for tasks" @moduledoc """ Lists all tasks or prints the documentation for a given task. ## Arguments mix help - prints all tasks and their shortdoc mix help TASK - prints full docs for the given task mix help --search PATTERN - prints all tasks that contain PATTERN in the name mix help --names - prints all task names and aliases (useful for autocompleting) ## Colors When possible, `mix help` is going to use coloring for formatting guides. The formatting can be customized by configuring the Mix application either inside your project (in `config/config.exs`) or by using the local config (in `~/.mix/config.exs`). For example, to disable, one may: [mix: [colors: [enabled: false]]] The available color options are: * `:enabled` - show ANSI formatting (defaults to `IO.ANSI.enabled?`) * `:doc_code` — the attributes for code blocks (cyan, bright) * `:doc_inline_code` - inline code (cyan) * `:doc_headings` - h1 and h2 (yellow, bright) * `:doc_title` — the overall heading for the output (reverse, yellow, bright) * `:doc_bold` - (bright) * `:doc_underline` - (underline) """ @spec run(OptionParser.argv) :: :ok def run(argv) def run([]) do loadpaths! modules = Mix.Task.load_all() {docs, max} = build_task_doc_list(modules) display_default_task_doc(max) display_task_doc_list(docs, max) display_iex_task_doc(max) end def run(["--names"]) do loadpaths! tasks = Mix.Task.load_all() |> Enum.map(&Mix.Task.task_name/1) aliases = Mix.Project.config[:aliases] |> Dict.keys |> Enum.map(&Atom.to_string/1) for info <- Enum.sort(aliases ++ tasks) do Mix.shell.info info end end def run(["--search", pattern]) do loadpaths! modules = Mix.Task.load_all() |> Enum.filter(&(String.contains?(Mix.Task.task_name(&1), pattern))) {docs, max} = build_task_doc_list(modules) display_task_doc_list(docs, max) end def run(["--search"]) do Mix.raise "Unexpected arguments, expected `mix help --search PATTERN`" end def run([task]) do loadpaths! module = Mix.Task.get!(task) doc = Mix.Task.moduledoc(module) || "There is no documentation for this task" opts = Application.get_env(:mix, :colors) if ansi_docs?(opts) do opts = [width: width] ++ opts IO.ANSI.Docs.print_heading("mix #{task}", opts) IO.ANSI.Docs.print(doc, opts) else IO.puts "# mix #{task}\n" IO.puts doc end IO.puts "Location: #{where_is_file(module)}" end def run(_) do Mix.raise "Unexpected arguments, expected `mix help` or `mix help TASK`" end # Loadpaths without checks because tasks may be defined in deps. defp loadpaths! do Mix.Task.run "loadpaths", ["--no-elixir-version-check", "--no-deps-check"] Mix.Task.reenable "loadpaths" end defp ansi_docs?(opts) do if Keyword.has_key?(opts, :enabled) do opts[:enabled] else IO.ANSI.enabled? end end defp width() do case :io.columns() do {:ok, width} -> min(width, 80) {:error, _} -> 80 end end defp format_task(task, max, doc) do String.ljust(task, max) <> " # " <> doc end defp where_is_file(module) do case :code.where_is_file(Atom.to_char_list(module) ++ '.beam') do :non_existing -> "not available" location -> location |> Path.dirname |> Path.expand |> Path.relative_to_cwd end end defp display_default_task_doc(max) do Mix.shell.info format_task("mix", max, "Run the default task (current: mix #{Mix.Project.config[:default_task]})") end defp display_iex_task_doc(max) do Mix.shell.info format_task("iex -S mix", max, "Start IEx and run the default task") end defp display_task_doc_list(docs, max) do Enum.each Enum.sort(docs), fn({task, doc}) -> Mix.shell.info format_task(task, max, doc) end end defp build_task_doc_list(modules) do Enum.reduce modules, {[], 0}, fn module, {docs, max} -> doc = Mix.Task.shortdoc(module) if doc do task = "mix " <> Mix.Task.task_name(module) docs = [{task, doc} | docs] max = max(byte_size(task), max) end {docs, max} end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/iex.ex000066400000000000000000000004061254730255300222730ustar00rootroot00000000000000defmodule Mix.Tasks.Iex do use Mix.Task @moduledoc """ A task that is simply meant to redirect users to `iex -S mix`. """ @spec run(OptionParser.argv) :: no_return def run(_) do Mix.raise "To use IEx with Mix, please run: iex -S mix" end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/loadconfig.ex000066400000000000000000000016111254730255300236120ustar00rootroot00000000000000defmodule Mix.Tasks.Loadconfig do use Mix.Task @shortdoc "Loads and persists the given configuration" @moduledoc """ Loads and persists the given configuration. In case no configuration file is given, it loads the project one at "config/config.exs" if it exists. Keep in mind though the "config/config.exs" file is always loaded by the CLI and invoking it is only required in cases you are starting Mix manually. This task is automatically reenabled, so it can be called multiple times to load different configs. """ @spec run(OptionParser.argv) :: :ok def run(args) do cond do file = Enum.at(args, 0) -> load file File.regular?("config/config.exs") -> load "config/config.exs" true -> :ok end Mix.Task.reenable "loadconfig" end defp load(file) do Mix.Config.persist Mix.Config.read!(file) :ok end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/loadpaths.ex000066400000000000000000000033101254730255300234620ustar00rootroot00000000000000defmodule Mix.Tasks.Loadpaths do use Mix.Task @moduledoc """ Loads the application and its dependencies paths. ## Command line options * `--no-deps-check` - do not check dependencies * `--no-elixir-version-check` - do not check elixir version """ @spec run(OptionParser.argv) :: :ok def run(args) do config = Mix.Project.config unless "--no-elixir-version-check" in args do check_elixir_version(config, args) end # --no-deps is used only internally. It has not purpose # from Mix.CLI because the CLI itself already loads deps. unless "--no-deps" in args do load_deps(config, args) end if config[:app] do load_project(config, args) end :ok end defp check_elixir_version(config, _) do if req = config[:elixir] do case Version.parse_requirement(req) do {:ok, req} -> unless Version.match?(System.version, req) do Mix.raise Mix.ElixirVersionError, target: config[:app] || Mix.Project.get, expected: req, actual: System.version end :error -> Mix.raise "Invalid Elixir version requirement #{req} in mix.exs file" end end end defp load_deps(_config, args) do unless "--no-deps-check" in args do Mix.Task.run "deps.check", args end Mix.Task.run "deps.loadpaths" end defp load_project(config, _args) do # Force recompile if we have an app and a version mismatch old_vsn = Mix.Dep.Lock.elixir_vsn if old_vsn && old_vsn != System.version, do: Mix.Dep.Lock.touch Enum.each Mix.Project.load_paths(config), &Code.prepend_path(&1) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/local.ex000066400000000000000000000012401254730255300225750ustar00rootroot00000000000000defmodule Mix.Tasks.Local do use Mix.Task @shortdoc "List local tasks" @moduledoc """ List local tasks. """ @spec run([]) :: :ok def run([]) do shell = Mix.shell modules = Mix.Local.all_tasks docs = for module <- modules do {Mix.Task.task_name(module), Mix.Task.shortdoc(module)} end max = Enum.reduce docs, 0, fn({task, _}, acc) -> max(byte_size(task), acc) end sorted = Enum.sort(docs) Enum.each sorted, fn({task, doc}) -> shell.info format('mix ~-#{max}s # ~ts', [task, doc]) end end defp format(expression, args) do :io_lib.format(expression, args) |> IO.iodata_to_binary end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/local.hex.ex000066400000000000000000000052551254730255300233720ustar00rootroot00000000000000defmodule Mix.Tasks.Local.Hex do use Mix.Task @hex_s3 "https://s3.amazonaws.com/s3.hex.pm" @hex_list_url @hex_s3 <> "/installs/list.csv" @hex_archive_url @hex_s3 <> "/installs/[VERSION]/hex.ez" @hex_requirement ">= 0.5.0" @shortdoc "Install hex locally" @moduledoc """ Install Hex locally. mix local.hex ## Command line options * `--force` - forces installation without a shell prompt; primarily intended for automation in build systems like make """ @spec run(OptionParser.argv) :: boolean def run(args) do version = get_matching_version() url = String.replace(@hex_archive_url, "[VERSION]", version) Mix.Tasks.Archive.Install.run [url, "--system" | args] end @doc false # Returns true if Hex is loaded or installed, otherwise returns false. @spec ensure_installed?(atom) :: boolean def ensure_installed?(app) do if Code.ensure_loaded?(Hex) do true else shell = Mix.shell shell.info "Could not find hex, which is needed to build dependency #{inspect app}" if shell.yes?("Shall I install hex?") do run ["--force"] else false end end end @doc false # Returns true if have required Hex, returns false if don't and don't update, # if update then exits. @spec ensure_updated?() :: boolean def ensure_updated?() do if Code.ensure_loaded?(Hex) do if Version.match?(Hex.version, @hex_requirement) do true else Mix.shell.info "Mix requires hex #{@hex_requirement} but you have #{Hex.version}" if Mix.shell.yes?("Shall I abort the current command and update hex?") do run ["--force"] exit({:shutdown, 0}) end false end else false end end @doc false def start do try do Hex.start catch kind, reason -> stacktrace = System.stacktrace Mix.shell.error "Could not start Hex. Try fetching a new version with " <> "`mix local.hex` or uninstalling it with `mix archive.uninstall hex.ez`" :erlang.raise(kind, reason, stacktrace) end end defp get_matching_version do Mix.Utils.read_path!(@hex_list_url, [system: true]) |> parse_csv |> all_eligibile_versions |> List.last end defp parse_csv(body) do :binary.split(body, "\n", [:global, :trim]) |> Enum.flat_map(fn line -> [_hex|elixirs] = :binary.split(line, ",", [:global, :trim]) elixirs end) |> Enum.uniq end defp all_eligibile_versions(versions) do {:ok, current_version} = Version.parse(System.version) Enum.filter(versions, &Version.compare(&1, current_version) != :gt) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/local.rebar.ex000066400000000000000000000022341254730255300236730ustar00rootroot00000000000000defmodule Mix.Tasks.Local.Rebar do use Mix.Task @rebar_url "http://s3.hex.pm/rebar" @shortdoc "Install rebar locally" @moduledoc """ Fetch a copy of rebar from the given path or url. It defaults to a rebar copy that ships with Elixir source if available or fetches it from #{@rebar_url}. The local copy is stored in your MIX_HOME (defaults to ~/.mix). This version of rebar will be used as required by `mix deps.compile`. ## Command line options * `--force` - forces installation without a shell prompt; primarily intended for automation in build systems like make """ @spec run(OptionParser.argv) :: true def run(argv) do {opts, argv, _} = OptionParser.parse(argv, switches: [force: :boolean]) path = case argv do [] -> @rebar_url [path|_] -> path end do_install(path, opts) end defp do_install(path, opts) do local_rebar_path = Mix.Rebar.local_rebar_path if Mix.Utils.copy_path!(path, local_rebar_path, opts) do :ok = :file.change_mode local_rebar_path, 0o755 Mix.shell.info [:green, "* creating ", :reset, Path.relative_to_cwd(local_rebar_path)] end true end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/new.ex000066400000000000000000000256731254730255300223140ustar00rootroot00000000000000defmodule Mix.Tasks.New do use Mix.Task import Mix.Generator import Mix.Utils, only: [camelize: 1, underscore: 1] @shortdoc "Create a new Elixir project" @moduledoc """ Creates a new Elixir project. It expects the path of the project as argument. mix new PATH [--sup] [--module MODULE] [--app APP] [--umbrella] A project at the given PATH will be created. The application name and module name will be retrieved from the path, unless `--module` or `--app` is given. A `--sup` option can be given to generate an OTP application skeleton including a supervision tree. Normally an app is generated without a supervisor and without the app callback. An `--umbrella` option can be given to generate an umbrella project. An `--app` option can be given in order to name the OTP application for the project. A `--module` option can be given in order to name the modules in the generated code skeleton. ## Examples mix new hello_world Is equivalent to: mix new hello_world --module HelloWorld To generate an app with supervisor and application callback: mix new hello_world --sup """ @spec run(OptionParser.argv) :: :ok def run(argv) do {opts, argv, _} = OptionParser.parse(argv, switches: [sup: :boolean, umbrella: :boolean]) case argv do [] -> Mix.raise "Expected PATH to be given, please use `mix new PATH`" [path|_] -> app = opts[:app] || Path.basename(Path.expand(path)) check_application_name!(app, !!opts[:app]) mod = opts[:module] || camelize(app) check_mod_name_validity!(mod) check_mod_name_availability!(mod) File.mkdir_p!(path) File.cd! path, fn -> if opts[:umbrella] do do_generate_umbrella(app, mod, path, opts) else do_generate(app, mod, path, opts) end end end end defp do_generate(app, mod, path, opts) do assigns = [app: app, mod: mod, otp_app: otp_app(mod, !!opts[:sup]), version: get_version(System.version)] create_file "README.md", readme_template(assigns) create_file ".gitignore", gitignore_text if in_umbrella? do create_file "mix.exs", mixfile_apps_template(assigns) else create_file "mix.exs", mixfile_template(assigns) end create_directory "config" create_file "config/config.exs", config_template(assigns) create_directory "lib" if opts[:sup] do create_file "lib/#{app}.ex", lib_sup_template(assigns) else create_file "lib/#{app}.ex", lib_template(assigns) end create_directory "test" create_file "test/test_helper.exs", test_helper_template(assigns) create_file "test/#{app}_test.exs", test_template(assigns) Mix.shell.info """ Your mix project was created successfully. You can use mix to compile it, test it, and more: cd #{path} mix test Run `mix help` for more commands. """ end defp otp_app(_mod, false) do " [applications: [:logger]]" end defp otp_app(mod, true) do " [applications: [:logger],\n mod: {#{mod}, []}]" end defp do_generate_umbrella(_app, mod, path, _opts) do assigns = [mod: mod] create_file ".gitignore", gitignore_text create_file "README.md", readme_template(assigns) create_file "mix.exs", mixfile_umbrella_template(assigns) create_directory "apps" create_directory "config" create_file "config/config.exs", config_umbrella_template(assigns) Mix.shell.info """ Your umbrella project was created successfully. Inside your project, you will find an apps/ directory where you can create and host many apps: cd #{path} cd apps mix new my_app Commands like `mix compile` and `mix test` when executed in the umbrella project root will automatically run for each application in the apps/ directory. """ end defp check_application_name!(name, from_app_flag) do unless name =~ ~r/^[a-z][\w_]*$/ do Mix.raise "Application name must start with a letter and have only lowercase " <> "letters, numbers and underscore, got: #{inspect name}" <> (if !from_app_flag do ". The application name is inferred from the path, if you'd like to " <> "explicitly name the application then use the `--app APP` option." else "" end) end end defp check_mod_name_validity!(name) do unless name =~ ~r/^[A-Z]\w*(\.[A-Z]\w*)*$/ do Mix.raise "Module name must be a valid Elixir alias (for example: Foo.Bar), got: #{inspect name}" end end defp check_mod_name_availability!(name) do name = Module.concat(Elixir, name) if Code.ensure_loaded?(name) do Mix.raise "Module name #{inspect name} is already taken, please choose another name" end end defp get_version(version) do {:ok, version} = Version.parse(version) "#{version.major}.#{version.minor}" <> case version.pre do [h|_] -> "-#{h}" [] -> "" end end defp in_umbrella? do apps = Path.dirname(File.cwd!) try do Mix.Project.in_project(:umbrella_check, "../..", fn _ -> path = Mix.Project.config[:apps_path] path && Path.expand(path) == apps end) catch _, _ -> false end end embed_template :readme, """ # <%= @mod %> **TODO: Add description** ## Installation 1. Add <%= @app %> to your list of dependencies in mix.exs: def deps do [{:<%= @app %>, "~> 0.0.1"}] end 2. Ensure <%= @app %> is started before your application: def application do [applications: [:<%= @app %>]] end """ embed_text :gitignore, """ /_build /cover /deps erl_crash.dump *.ez """ embed_template :mixfile, """ defmodule <%= @mod %>.Mixfile do use Mix.Project def project do [app: :<%= @app %>, version: "0.0.1", elixir: "~> <%= @version %>", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end # Configuration for the OTP application # # Type `mix help compile.app` for more information def application do <%= @otp_app %> end # Dependencies can be Hex packages: # # {:mydep, "~> 0.3.0"} # # Or git/path repositories: # # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} # # Type `mix help deps` for more examples and options defp deps do [] end end """ embed_template :mixfile_apps, """ defmodule <%= @mod %>.Mixfile do use Mix.Project def project do [app: :<%= @app %>, version: "0.0.1", deps_path: "../../deps", lockfile: "../../mix.lock", elixir: "~> <%= @version %>", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end # Configuration for the OTP application # # Type `mix help compile.app` for more information def application do <%= @otp_app %> end # Dependencies can be Hex packages: # # {:mydep, "~> 0.3.0"} # # Or git/path repositories: # # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} # # To depend on another app inside the umbrella: # # {:myapp, in_umbrella: true} # # Type `mix help deps` for more examples and options defp deps do [] end end """ embed_template :mixfile_umbrella, """ defmodule <%= @mod %>.Mixfile do use Mix.Project def project do [apps_path: "apps", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end # Dependencies can be Hex packages: # # {:mydep, "~> 0.3.0"} # # Or git/path repositories: # # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} # # Type `mix help deps` for more examples and options. # # Dependencies listed here are available only for this project # and cannot be accessed from applications inside the apps folder defp deps do [] end end """ embed_template :config, ~S""" # This file is responsible for configuring your application # and its dependencies with the aid of the Mix.Config module. use Mix.Config # This configuration is loaded before any dependency and is restricted # to this project. If another project depends on this project, this # file won't be loaded nor affect the parent project. For this reason, # if you want to provide default values for your application for third- # party users, it should be done in your mix.exs file. # Sample configuration: # # config :logger, # level: :info # # config :logger, :console, # format: "$date $time [$level] $metadata$message\n", # metadata: [:user_id] # It is also possible to import configuration files, relative to this # directory. For example, you can emulate configuration per environment # by uncommenting the line below and defining dev.exs, test.exs and such. # Configuration from the imported file will override the ones defined # here (which is why it is important to import them last). # # import_config "#{Mix.env}.exs" """ embed_template :config_umbrella, ~S""" # This file is responsible for configuring your application # and its dependencies with the aid of the Mix.Config module. use Mix.Config # The configuration defined here will only affect the dependencies # in the apps directory when commands are executed from the umbrella # project. For this reason, it is preferred to configure each child # application directly and import its configuration, as done below. import_config "../apps/*/config/config.exs" # Sample configuration (overrides the imported configuration above): # # config :logger, :console, # level: :info, # format: "$date $time [$level] $metadata$message\n", # metadata: [:user_id] """ embed_template :lib, """ defmodule <%= @mod %> do end """ embed_template :lib_sup, """ defmodule <%= @mod %> do use Application # See http://elixir-lang.org/docs/stable/elixir/Application.html # for more information on OTP Applications def start(_type, _args) do import Supervisor.Spec, warn: false children = [ # Define workers and child supervisors to be supervised # worker(<%= @mod %>.Worker, [arg1, arg2, arg3]), ] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: <%= @mod %>.Supervisor] Supervisor.start_link(children, opts) end end """ embed_template :test, """ defmodule <%= @mod %>Test do use ExUnit.Case doctest <%= @mod %> test "the truth" do assert 1 + 1 == 2 end end """ embed_template :test_helper, """ ExUnit.start() """ end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/run.ex000066400000000000000000000063711254730255300223210ustar00rootroot00000000000000defmodule Mix.Tasks.Run do use Mix.Task @shortdoc "Runs the given file or expression" @moduledoc """ Runs the given file or expression in the context of the application. You can use this task to execute a particular file or command: mix run -e Hello.world mix run my_script.exs This task provides a subset of the functionality available in the `elixir` executable, including setting up the `System.argv`: mix run my_script.exs arg1 arg2 arg3 You can also use this task to simply start an application and keep it running without halting: mix run --no-halt Before running any command, the task compiles and starts the current application. Those can be configured with the options below. You may also pass option specific to the `elixir` executable as follows: elixir --sname hello -S mix run --no-halt ## Command line options * `--config`, `-c` - loads the given configuration file * `--eval`, `-e` - evaluate the given code * `--require`, `-r` - require pattern before running the command * `--parallel-require`, `-pr` - requires pattern in parallel * `--no-compile` - do not compile even if files require compilation * `--no-deps-check` - do not check dependencies * `--no-halt` - do not halt the system after running the command * `--no-start` - do not start applications after compilation """ @spec run(OptionParser.argv) :: :ok def run(args) do {opts, head, _} = OptionParser.parse_head(args, aliases: [r: :require, pr: :parallel_require, e: :eval, c: :config], switches: [parallel_require: :keep, require: :keep, eval: :keep, config: :keep, halt: :boolean, compile: :boolean, deps_check: :boolean, start: :boolean]) {file, argv} = case {Keyword.has_key?(opts, :eval), head} do {true, _} -> {nil, head} {_, [h|t]} -> {h, t} {_, []} -> {nil, []} end System.argv(argv) process_config opts # Start app after rewriting System.argv, # but before requiring and evaling Mix.Task.run "app.start", args process_load opts _ = if file do if File.regular?(file) do Code.require_file(file) else Mix.raise "No such file: #{file}" end end unless Keyword.get(opts, :halt, true), do: :timer.sleep(:infinity) :ok end defp process_config(opts) do Enum.each opts, fn {:config, value} -> Mix.Task.run "loadconfig", [value] _ -> :ok end end defp process_load(opts) do Enum.each opts, fn {:parallel_require, value} -> case filter_patterns(value) do [] -> Mix.raise "No files matched pattern #{inspect value} given to --parallel-require" filtered -> Kernel.ParallelRequire.files(filtered) end {:require, value} -> case filter_patterns(value) do [] -> Mix.raise "No files matched pattern #{inspect value} given to --require" filtered -> Enum.each(filtered, &Code.require_file(&1)) end {:eval, value} -> Code.eval_string(value) _ -> :ok end end defp filter_patterns(pattern) do Enum.filter(Enum.uniq(Path.wildcard(pattern)), &File.regular?(&1)) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks/test.ex000066400000000000000000000203031254730255300224630ustar00rootroot00000000000000defmodule Mix.Tasks.Test do defmodule Cover do @moduledoc false def start(compile_path, opts) do Mix.shell.info "Cover compiling modules ... " _ = :cover.start case :cover.compile_beam_directory(compile_path |> to_char_list) do results when is_list(results) -> :ok {:error, _} -> Mix.raise "Failed to cover compile directory: " <> compile_path end output = opts[:output] fn() -> Mix.shell.info "\nGenerating cover results ... " File.mkdir_p!(output) Enum.each :cover.modules, fn(mod) -> {:ok, _} = :cover.analyse_to_file(mod, '#{output}/#{mod}.html', [:html]) end end end end use Mix.Task @shortdoc "Run a project's tests" @recursive true @moduledoc """ Run the tests for a project. This task starts the current application, loads up `test/test_helper.exs` and then requires all files matching the `test/**/_test.exs` pattern in parallel. A list of files can be given after the task name in order to select the files to compile: mix test test/some/particular/file_test.exs ## Command line options * `--trace` - run tests with detailed reporting; automatically sets `--max-cases` to 1 * `--max-cases` - set the maximum number of cases running async * `--cover` - the directory to include coverage results * `--force` - forces compilation regardless of modification times * `--no-compile` - do not compile, even if files require compilation * `--no-start` - do not start applications after compilation * `--no-color` - disable color in the output * `--color` - enable color in the output * `--include` - include tests that match the filter * `--exclude` - exclude tests that match the filter * `--only` - run only tests that match the filter * `--seed` - seeds the random number generator used to randomize tests order * `--timeout` - set the timeout for the tests ## Filters ExUnit provides tags and filtering functionality that allows developers to select which tests to run. The most common functionality is to exclude some particular tests from running by default in your test helper file: # Exclude all external tests from running ExUnit.configure exclude: [external: true] Then, whenever desired, those tests could be included in the run via the `--include` flag: mix test --include external:true The example above will run all tests that have the external flag set to `true`. It is also possible to include all examples that have a given tag, regardless of its value: mix test --include external Note that all tests are included by default, so unless they are excluded first (either in the test helper or via the `--exclude` option), the `--include` flag has no effect. For this reason, mix also provides an `--only` option that excludes all tests and includes only the given ones: mix test --only external Which is equivalent to: mix test --include external --exclude test In case a single file is being tested, it is possible pass a specific line number: mix test test/some/particular/file_test.exs:12 Which is equivalent to: mix test --only line:12 test/some/particular/file_test.exs ## Configuration * `:test_paths` - list of paths containing test files, defaults to `["test"]`. It is expected all test paths to contain a `test_helper.exs` file. * `:test_pattern` - a pattern to load test files, defaults to `*_test.exs`. * `:test_coverage` - a set of options to be passed down to the coverage mechanism. ## Coverage The `:test_coverage` configuration accepts the following options: * `:output` - the output for cover results, defaults to `"cover"` * `:tool` - the coverage tool By default, a very simple wrapper around OTP's `cover` is used as a tool, but it can be overridden as follows: test_coverage: [tool: CoverModule] `CoverModule` can be any module that exports `start/2`, receiving the compilation path and the `test_coverage` options as arguments. It must return an anonymous function of zero arity that will be run after the test suite is done or `nil`. """ @switches [force: :boolean, color: :boolean, cover: :boolean, trace: :boolean, max_cases: :integer, include: :keep, exclude: :keep, seed: :integer, only: :keep, compile: :boolean, start: :boolean, timeout: :integer] @cover [output: "cover", tool: Cover] @spec run(OptionParser.argv) :: :ok def run(args) do {opts, files, _} = OptionParser.parse(args, switches: @switches) unless System.get_env("MIX_ENV") || Mix.env == :test do Mix.raise "mix test is running on environment #{Mix.env}. If you are " <> "running tests along another task, please set MIX_ENV explicitly" end Mix.Task.run "loadpaths", args if Keyword.get(opts, :compile, true) do Mix.Project.compile(args) end project = Mix.Project.config cover = Keyword.merge(@cover, project[:test_coverage] || []) # Start cover after we load deps but before we start the app. cover = if opts[:cover] do cover[:tool].start(Mix.Project.compile_path(project), cover) end # Start the app and configure exunit with command line options # before requiring test_helper.exs so that the configuration is # available in test_helper.exs. Then configure exunit again so # that command line options override test_helper.exs Mix.shell.print_app Mix.Task.run "app.start", args # Ensure ex_unit is loaded. case Application.load(:ex_unit) do :ok -> :ok {:error, {:already_loaded, :ex_unit}} -> :ok end opts = ex_unit_opts(opts) ExUnit.configure(opts) test_paths = project[:test_paths] || ["test"] Enum.each(test_paths, &require_test_helper(&1)) ExUnit.configure(opts) # Finally parse, require and load the files test_files = parse_files(files, test_paths) test_pattern = project[:test_pattern] || "*_test.exs" test_files = Mix.Utils.extract_files(test_files, test_pattern) _ = Kernel.ParallelRequire.files(test_files) # Run the test suite, coverage tools and register an exit hook %{failures: failures} = ExUnit.run if cover, do: cover.() System.at_exit fn _ -> if failures > 0, do: exit({:shutdown, 1}) end end @doc false def ex_unit_opts(opts) do opts = opts |> filter_opts(:include) |> filter_opts(:exclude) |> filter_only_opts() default_opts(opts) ++ Dict.take(opts, [:trace, :max_cases, :include, :exclude, :seed, :timeout]) end defp default_opts(opts) do # Set autorun to false because Mix # automatically runs the test suite for us. case Dict.get(opts, :color) do nil -> [autorun: false] enabled? -> [autorun: false, colors: [enabled: enabled?]] end end defp parse_files([], test_paths) do test_paths end defp parse_files([single_file], _test_paths) do # Check if the single file path matches test/path/to_test.exs:123, if it does # apply `--only line:123` and trim the trailing :123 part. {single_file, opts} = ExUnit.Filters.parse_path(single_file) ExUnit.configure(opts) [single_file] end defp parse_files(files, _test_paths) do files end defp parse_filters(opts, key) do if Keyword.has_key?(opts, key) do ExUnit.Filters.parse(Keyword.get_values(opts, key)) end end defp filter_opts(opts, key) do if filters = parse_filters(opts, key) do Keyword.put(opts, key, filters) else opts end end defp filter_only_opts(opts) do if filters = parse_filters(opts, :only) do opts |> Keyword.put_new(:include, []) |> Keyword.put_new(:exclude, []) |> Keyword.update!(:include, &(filters ++ &1)) |> Keyword.update!(:exclude, &[:test|&1]) else opts end end defp require_test_helper(dir) do file = Path.join(dir, "test_helper.exs") if File.exists?(file) do Code.require_file file else Mix.raise "Cannot run tests because test helper file #{inspect file} does not exist" end end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/tasks_server.ex000066400000000000000000000011721254730255300230750ustar00rootroot00000000000000defmodule Mix.TasksServer do @moduledoc false def start_link() do Agent.start_link(fn -> HashSet.new end, name: __MODULE__) end def clear() do update fn _ -> HashSet.new end end def run(tuple) do get_and_update fn set -> {not(tuple in set), Set.put(set, tuple)} end end def put(tuple) do update &Set.put(&1, tuple) end def delete_many(many) do update &Enum.reduce(many, &1, fn x, acc -> Set.delete(acc, x) end) end defp get_and_update(fun) do Agent.get_and_update(__MODULE__, fun, 30_000) end defp update(fun) do Agent.update(__MODULE__, fun, 30_000) end end elixir-lang-1.1.0~0.20150708/lib/mix/lib/mix/utils.ex000066400000000000000000000336701254730255300215320ustar00rootroot00000000000000defmodule Mix.Utils do @moduledoc """ Utilities used throughout Mix and tasks. """ @doc """ Get the mix home. It defaults to `~/.mix` unless the `MIX_HOME` environment variable is set. Developers should only store entries in the `MIX_HOME` directory which are guaranteed to work across multiple Elixir versions, as it is not recommended to swap the `MIX_HOME` directory as configuration and other important data may be stored there. """ def mix_home do System.get_env("MIX_HOME") || Path.expand("~/.mix") end @doc """ Get all paths defined in the MIX_PATH env variable. `MIX_PATH` may contain multiple paths. If on Windows, those paths should be separated by `;`, if on unix systems, use `:`. """ def mix_paths do if path = System.get_env("MIX_PATH") do String.split(path, path_separator) else [] end end defp path_separator do case :os.type do {:win32, _} -> ";" {:unix, _} -> ":" end end @doc """ Take a `command` name and attempts to load a module with the command name converted to a module name in the given `at` scope. Returns `{:module, module}` in case a module exists and is loaded, `{:error, reason}` otherwise. ## Examples iex> Mix.Utils.command_to_module("compile", Mix.Tasks) {:module, Mix.Tasks.Compile} """ def command_to_module(command, at \\ Elixir) do module = Module.concat(at, command_to_module_name(command)) Code.ensure_loaded(module) end @doc """ Returns `true` if any of the `sources` are stale compared to the given `targets`. """ def stale?(sources, targets) do Enum.any? stale_stream(sources, targets) end @doc """ Extract all stale `sources` compared to the given `targets`. """ def extract_stale(_sources, []), do: [] def extract_stale([], _targets), do: [] def extract_stale(sources, targets) do stale_stream(sources, targets) |> Enum.to_list end defp stale_stream(sources, targets) do modified_target = targets |> Enum.map(&last_modified(&1)) |> Enum.min Stream.filter(sources, fn(source) -> last_modified(source) > modified_target end) end @doc """ Returns the date the given path was last modified. If the path does not exist, it returns the unix epoch (1970-01-01 00:00:00). """ def last_modified(path) def last_modified({{_, _, _}, {_, _, _}} = timestamp) do timestamp end def last_modified(path) do now = :calendar.local_time case File.stat(path) do {:ok, %File.Stat{mtime: mtime}} when mtime > now -> Mix.shell.error("warning: mtime (modified time) for \"#{path}\" was set to the future, resetting to now") File.touch!(path, now) mtime {:ok, %File.Stat{mtime: mtime}} -> mtime {:error, _} -> {{1970, 1, 1}, {0, 0, 0}} end end @doc """ Extract files from a list of paths. `exts_or_pattern` may be a list of extensions or a `Path.wildcard/1` pattern. If the path in `paths` is a file, it is included in the return result. If it is a directory, it is searched recursively for files with the given extensions or matching the given patterns. """ def extract_files(paths, exts_or_pattern) def extract_files(paths, exts) when is_list(exts) do extract_files(paths, "*.{#{Enum.join(exts, ",")}}") end def extract_files(paths, pattern) do Enum.flat_map(paths, fn path -> if File.regular?(path), do: [path], else: Path.wildcard("#{path}/**/#{pattern}") end) |> Enum.uniq end @doc """ Converts the given atom or binary to underscore format. If an atom is given, it is assumed to be an Elixir module, so it is converted to a binary and then processed. ## Examples iex> Mix.Utils.underscore "FooBar" "foo_bar" iex> Mix.Utils.underscore "Foo.Bar" "foo/bar" iex> Mix.Utils.underscore Foo.Bar "foo/bar" In general, `underscore` can be thought of as the reverse of `camelize`, however, in some cases formatting may be lost: iex> Mix.Utils.underscore "SAPExample" "sap_example" iex> Mix.Utils.camelize "sap_example" "SapExample" """ def underscore(atom) when is_atom(atom) do "Elixir." <> rest = Atom.to_string(atom) underscore(rest) end def underscore(""), do: "" def underscore(<>) do <> <> do_underscore(t, h) end defp do_underscore(<>, _) when h in ?A..?Z and not (t in ?A..?Z or t == ?.) do <> <> do_underscore(rest, t) end defp do_underscore(<>, prev) when h in ?A..?Z and not prev in ?A..?Z do <> <> do_underscore(t, h) end defp do_underscore(<>, _) do <> <> underscore(t) end defp do_underscore(<>, _) do <> <> do_underscore(t, h) end defp do_underscore(<<>>, _) do <<>> end @doc """ Converts the given string to CamelCase format. ## Examples iex> Mix.Utils.camelize "foo_bar" "FooBar" """ @spec camelize(String.t) :: String.t def camelize(string) def camelize(""), do: "" def camelize(<>), do: camelize(t) def camelize(<>), do: <> <> do_camelize(t) defp do_camelize(<>), do: do_camelize(<< ?_, t :: binary >>) defp do_camelize(<>) when h in ?a..?z, do: <> <> do_camelize(t) defp do_camelize(<>), do: <<>> defp do_camelize(<>), do: <> <> camelize(t) defp do_camelize(<>), do: <> <> do_camelize(t) defp do_camelize(<<>>), do: <<>> @doc """ Takes a module and converts it to a command. The nesting argument can be given in order to remove the nesting of a module. ## Examples iex> Mix.Utils.module_name_to_command(Mix.Tasks.Compile, 2) "compile" iex> Mix.Utils.module_name_to_command("Mix.Tasks.Compile.Elixir", 2) "compile.elixir" """ def module_name_to_command(module, nesting \\ 0) def module_name_to_command(module, nesting) when is_atom(module) do module_name_to_command(inspect(module), nesting) end def module_name_to_command(module, nesting) do t = Regex.split(~r/\./, to_string(module)) t |> Enum.drop(nesting) |> Enum.map(&underscore(&1)) |> Enum.join(".") end @doc """ Takes a command and converts it to the module name format. ## Examples iex> Mix.Utils.command_to_module_name("compile.elixir") "Compile.Elixir" """ def command_to_module_name(s) do Regex.split(~r/\./, to_string(s)) |> Enum.map(&camelize(&1)) |> Enum.join(".") end defp to_upper_char(char) when char in ?a..?z, do: char - 32 defp to_upper_char(char), do: char defp to_lower_char(char) when char in ?A..?Z, do: char + 32 defp to_lower_char(char), do: char @doc """ Symlink directory `source` to `target` or copy it recursively in case symlink fails. Expect source and target to be absolute paths as it generates a relative symlink. """ def symlink_or_copy(source, target) do if File.exists?(source) do # Relative symbolic links on windows are broken link = case :os.type do {:win32, _} -> source _ -> make_relative_path(source, target) end |> String.to_char_list case :file.read_link(target) do {:ok, ^link} -> :ok {:ok, _} -> File.rm!(target) do_symlink_or_copy(source, target, link) {:error, :enoent} -> do_symlink_or_copy(source, target, link) {:error, _} -> _ = File.rm_rf!(target) do_symlink_or_copy(source, target, link) end else {:error, :enoent} end end defp do_symlink_or_copy(source, target, link) do case :file.make_symlink(link, target) do :ok -> :ok {:error, _} -> {:ok, File.cp_r!(source, target)} end end # Make a relative path between the two given paths. # Expects both paths to be fully expanded. defp make_relative_path(source, target) do do_make_relative_path(Path.split(source), Path.split(target)) end defp do_make_relative_path([h|t1], [h|t2]) do do_make_relative_path(t1, t2) end defp do_make_relative_path(source, target) do base = List.duplicate("..", max(length(target) - 1, 0)) Path.join(base ++ source) end @doc """ Opens and reads content from either a URL or a local filesystem path and returns the contents as a binary. Raises if the given path is not a URL, nor a file or if the file or URL are invalid. ## Options * `:system` - Boolean value forces the use of `wget` or `curl` to fetch the file if the given path is a URL. """ def read_path!(path, opts \\ []) do cond do url?(path) && opts[:system] -> read_shell(path, nil) url?(path) -> read_httpc(path, nil) file?(path) -> read_file(path) true -> Mix.raise "Expected #{path} to be a url or a local file path" end end @doc """ Copies content from either a URL or a local filesystem path to target path. Used by tasks like `archive.install` and `local.rebar` that support installation either from a URL or a local file. Raises if the given path is not a URL, nor a file or if the file or URL are invalid. ## Options * `:system` - Boolean value forces the use of `wget` or `curl` to fetch the file if the given path is a URL. * `:force` - Forces overwriting target file without a shell prompt. """ def copy_path!(source, target, opts \\ []) when is_binary(source) and is_binary(target) do if opts[:force] || overwriting?(target) do cond do url?(source) && opts[:system] -> read_shell(source, target) url?(source) -> read_httpc(source, target) file?(source) -> copy_file(source, target) true -> Mix.raise "Expected #{source} to be a url or a local file path" end true else false end end @doc """ Prompts the user to overwrite the file if it exists. Returns the user input. """ def overwriting?(path) do if File.exists?(path) do full = Path.expand(path) Mix.shell.yes?(Path.relative_to_cwd(full) <> " already exists, overwrite?") else true end end defp read_file(path) do File.read!(path) end defp copy_file(source, target) do File.mkdir_p!(Path.dirname(target)) File.cp!(source, target) end defp read_httpc(path, target) do {:ok, _} = Application.ensure_all_started(:ssl) {:ok, _} = Application.ensure_all_started(:inets) # Starting a http client profile allows us to scope # the effects of using a http proxy to this function {:ok, _pid} = :inets.start(:httpc, [{:profile, :mix}]) headers = [{'user-agent', 'Mix/#{System.version}'}] request = {:binary.bin_to_list(path), headers} # If a proxy environment variable was supplied add a proxy to httpc http_proxy = System.get_env("HTTP_PROXY") || System.get_env("http_proxy") https_proxy = System.get_env("HTTPS_PROXY") || System.get_env("https_proxy") if http_proxy, do: proxy(:proxy, http_proxy) if https_proxy, do: proxy(:https_proxy, https_proxy) if target do File.mkdir_p!(Path.dirname(target)) File.rm(target) req_opts = [stream: String.to_char_list(target)] else req_opts = [body_format: :binary] end # We are using relaxed: true because some servers is returning a Location # header with relative paths, which does not follow the spec. This would # cause the request to fail with {:error, :no_scheme} unless :relaxed # is given. case :httpc.request(:get, request, [relaxed: true], req_opts, :mix) do {:ok, :saved_to_file} -> :ok {:ok, {{_, status, _}, _, body}} when status in 200..299 -> body {:ok, {{_, status, _}, _, _}} -> Mix.raise "Could not access url #{path}, got status: #{status}" {:error, reason} -> Mix.raise "Could not access url #{path}, error: #{inspect reason}" end after :inets.stop(:httpc, :mix) end defp proxy(proxy_scheme, proxy) do uri = URI.parse(proxy) if uri.host && uri.port do host = String.to_char_list(uri.host) :httpc.set_options([{proxy_scheme, {{host, uri.port}, []}}], :mix) end end defp read_shell(path, target) do filename = URI.parse(path).path |> Path.basename out_path = target || Path.join(System.tmp_dir!, filename) File.mkdir_p!(Path.dirname(out_path)) File.rm(out_path) status = cond do windows? && System.find_executable("powershell") -> command = ~s[$ErrorActionPreference = 'Stop'; ] <> ~s[$client = new-object System.Net.WebClient; ] <> ~s[$client.DownloadFile(\\"#{path}\\", \\"#{out_path}\\")] Mix.shell.cmd(~s[powershell -Command "& {#{command}}"]) System.find_executable("curl") -> Mix.shell.cmd(~s[curl -sSL -o "#{out_path}" "#{path}"]) System.find_executable("wget") -> Mix.shell.cmd(~s[wget -nv -O "#{out_path}" "#{path}"]) windows? -> Mix.shell.error "powershell, wget or curl not installed" true -> Mix.shell.error "wget or curl not installed" 1 end check_command!(status, path, target) unless target do data = File.read!(out_path) File.rm!(out_path) data end end defp check_command!(0, _path, _out_path), do: :ok defp check_command!(_status, path, nil) do Mix.raise "Could not fetch data, please download manually from " <> "#{inspect path}" end defp check_command!(_status, path, out_path) do Mix.raise "Could not fetch data, please download manually from " <> "#{inspect path} and copy it to #{inspect out_path}" end defp windows? do match?({:win32, _}, :os.type) end defp file?(path) do File.regular?(path) end defp url?(path) do URI.parse(path).scheme in ["http", "https"] end end elixir-lang-1.1.0~0.20150708/lib/mix/mix.exs000066400000000000000000000005101254730255300177720ustar00rootroot00000000000000defmodule Mix.Mixfile do use Mix.Project def project do [app: :mix, build_per_environment: false, version: System.version, escript: [main_module: Mix.CLI]] end def application do [registered: [Mix.State, Mix.TasksServer, Mix.ProjectStack], mod: {Mix, []}, env: [colors: []]] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/000077500000000000000000000000001254730255300174375ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/000077500000000000000000000000001254730255300213105ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/.gitignore000066400000000000000000000000441254730255300232760ustar00rootroot00000000000000git_repo deps_on_git_repo git_rebar elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/archive/000077500000000000000000000000001254730255300227315ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/archive/ebin/000077500000000000000000000000001254730255300236465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/archive/ebin/Elixir.Mix.Tasks.Local.Sample.beam000066400000000000000000000043641254730255300320300ustar00rootroot00000000000000FOR1BEAMAtomElixir.Mix.Tasks.Local.Sample__info__docs functions moduledocmodulemacrosrun Elixir.Mixshellinfo module_infoerlangget_module_infoCode" 0;25BERUberu0@G@@GP@G `@p@ @@#@G0 q@NЙ@@N StrTImpT(  ExpT4   LitT{x=A E?eM7L̈F xǐy30ʒ*ǙIӄP0r x3"sEޭs=]Uho3KZwbv"LocTAttr|lhdvsnlnR+3|4.8jhd behaviourldElixir.Mix.TaskjhdshortdoclmA local install samplejjCInflhdoptionsld debug_infojhdversionk4.9.1hdtimehbaaaaa hdsourcekG/Volumes/Work/github/elixir/lib/mix/test/fixtures/beams/local.sample.exjAbstPxWr4vI[ pL  Kb+YHr1+dNiJIQ$7OMq S.]z}/ˌ*%=̩m^é4th_oiu+-!}=23 (TJ& sp bX~>n8p/6g@"ܗ +M;+!dHIMvᄒSXF&R'\rn/Uk]L%=°確0GNF ]Eh] xo ;ztNx*v+g3Go vpS/ۚRv%3UQL8jvΦU;.s·@-=C s,F}ߜpyeUp#KY  P_sz/Tw ,Ql+7/ݖ Ԭ*sNZK L)5>+$CζL# X`=y8I_ term(). -record(br, {cell=undefined}). b() -> #br{cell=specified}. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_erlang/src/c.erl000066400000000000000000000001401254730255300260000ustar00rootroot00000000000000-module(c). -compile(export_all). -include("r.hrl"). -behaviour(b). c() -> #r{cell=specified}.elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_leex/000077500000000000000000000000001254730255300237555ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_leex/src/000077500000000000000000000000001254730255300245445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_leex/src/test_ok.xrl000066400000000000000000000012071254730255300267430ustar00rootroot00000000000000Definitions. Add = (\+|-) Number = [0-9] Rules. {Add} : make_token(add_op, TokenLine, TokenChars). {Number}+ : make_token(integer, TokenLine, TokenChars, fun erlang:list_to_integer/1). Erlang code. make_token(Name, Line, Chars) when is_list(Chars) -> {token, {Name, Line, list_to_atom(Chars)}}; make_token(Name, Line, Chars) -> {token, {Name, Line, Chars}}. make_token(Name, Line, Chars, Fun) -> {token, {Name, Line, Fun(Chars)}}. endls(Chars) -> lists:filter(fun (C) -> C == $\n orelse C == $; end, Chars). is_reserved("if") -> true; is_reserved(_) -> false. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_yecc/000077500000000000000000000000001254730255300237435ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_yecc/src/000077500000000000000000000000001254730255300245325ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/compile_yecc/src/test_ok.yrl000066400000000000000000000014361254730255300267360ustar00rootroot00000000000000Nonterminals Elements Value IfBlock IfBraced IfExpression ElseBraced EndIfBraced. Terminals close_tag endif_keyword if_keyword else_keyword open_tag not_keyword text. Rootsymbol Elements. Value -> '$empty' : []. Elements -> '$empty' : []. Elements -> Elements text : '$1' ++ ['$2']. Elements -> Elements IfBlock : '$1' ++ ['$2']. IfBlock -> IfBraced Elements ElseBraced Elements EndIfBraced : {ifelse, '$1', '$2', '$4'}. IfBlock -> IfBraced Elements EndIfBraced : {'if', '$1', '$2'}. IfBraced -> open_tag if_keyword IfExpression close_tag : '$3'. IfExpression -> not_keyword IfExpression : {'not', '$2'}. IfExpression -> Value : '$1'. ElseBraced -> open_tag else_keyword close_tag. EndIfBraced -> open_tag endif_keyword close_tag. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/000077500000000000000000000000001254730255300227405ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/bad_app.exs000066400000000000000000000000201254730255300250370ustar00rootroot00000000000000[sample: :oops] elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/bad_import.exs000066400000000000000000000000541254730255300256000ustar00rootroot00000000000000use Mix.Config import_config "bad_root.exs"elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/bad_root.exs000066400000000000000000000000061254730255300252460ustar00rootroot00000000000000:oops elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/good_config.exs000066400000000000000000000000271254730255300257350ustar00rootroot00000000000000[my_app: [key: :value]]elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/good_import.exs000066400000000000000000000000651254730255300260040ustar00rootroot00000000000000use Mix.Config import_config "good_config.exs" :done elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/configs/nested.exs000066400000000000000000000000661254730255300247450ustar00rootroot00000000000000use Mix.Config config :app, Repo, key: [nested: true] elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/000077500000000000000000000000001254730255300236465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/000077500000000000000000000000001254730255300251045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/000077500000000000000000000000001254730255300256625ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/000077500000000000000000000000001254730255300264305ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidapp/000077500000000000000000000000001254730255300305575ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidapp/ebin/000077500000000000000000000000001254730255300314745ustar00rootroot00000000000000invalidapp.app000066400000000000000000000000711254730255300342440ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidapp/ebin{application, invalidsomethingelse, [ {vsn,"0.1.0"} ]}.elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidvsn/000077500000000000000000000000001254730255300306055ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidvsn/ebin/000077500000000000000000000000001254730255300315225ustar00rootroot00000000000000invalidvsn.app000066400000000000000000000000521254730255300343170ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidvsn/ebin{application, invalidvsn, [ {vsn,ok} ]}.elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/ok/000077500000000000000000000000001254730255300270415ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/ok/ebin/000077500000000000000000000000001254730255300277565ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/_build/dev/lib/ok/ebin/ok.app000066400000000000000000000000471254730255300310720ustar00rootroot00000000000000{application, ok, [ {vsn,"0.1.0"} ]}.elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/000077500000000000000000000000001254730255300251605ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/bad_deps_repo/000077500000000000000000000000001254730255300277465ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/bad_deps_repo/mix.exs000066400000000000000000000003511254730255300312630ustar00rootroot00000000000000defmodule BadDepsRepo do use Mix.Project def project do [ app: :bad_deps_repo, version: "0.1.0", deps: [ {:git_repo, "0.0.0", git: MixTest.Case.fixture_path("bad_git_repo")} ] ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/deps_repo/000077500000000000000000000000001254730255300271405ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/deps_repo/mix.exs000066400000000000000000000003351254730255300304570ustar00rootroot00000000000000defmodule DepsRepo do use Mix.Project def project do [ app: :deps_repo, version: "0.1.0", deps: [ {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end endelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/noscm_repo/000077500000000000000000000000001254730255300273245ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/noscm_repo/mix.exs000066400000000000000000000002561254730255300306450ustar00rootroot00000000000000defmodule NoSCMRepo do use Mix.Project def project do [ app: :noscm_repo, version: "0.1.0", deps: [ {:git_repo, "0.1.0"} ] ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/raw_repo/000077500000000000000000000000001254730255300267765ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/raw_repo/lib/000077500000000000000000000000001254730255300275445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/raw_repo/lib/raw_repo.ex000066400000000000000000000000711254730255300317160ustar00rootroot00000000000000defmodule RawRepo do def hello do "world" end endelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/custom/raw_repo/mix.exs000066400000000000000000000002371254730255300303160ustar00rootroot00000000000000defmodule RawRepo.Mix do use Mix.Project def project do Mix.shell.info ":raw_repo env is #{Mix.env}" [app: :raw_repo, version: "0.1.0"] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/000077500000000000000000000000001254730255300246015ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/invalidapp/000077500000000000000000000000001254730255300267305ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/invalidapp/mix.exs000066400000000000000000000001751254730255300302510ustar00rootroot00000000000000defmodule InvalidApp.Mixfile do use Mix.Project def project do [ app: :invalidapp, version: "1.0" ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/invalidvsn/000077500000000000000000000000001254730255300267565ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/invalidvsn/.gitkeep000066400000000000000000000000001254730255300303750ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/ok/000077500000000000000000000000001254730255300252125ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/ok/mix.exs000066400000000000000000000001571254730255300265330ustar00rootroot00000000000000defmodule Ok.Mixfile do use Mix.Project def project do [ app: :ok, version: "0.1.0" ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/ok/priv/000077500000000000000000000000001254730255300261725ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/deps_status/deps/ok/priv/sample000066400000000000000000000000061254730255300273720ustar00rootroot00000000000000SAMPLEelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/000077500000000000000000000000001254730255300236615ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/config/000077500000000000000000000000001254730255300251265ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/config/config.exs000066400000000000000000000000741254730255300271150ustar00rootroot00000000000000use Mix.Config config :escripttest, erlval: "Erlang value" elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/lib/000077500000000000000000000000001254730255300244275ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/lib/escripttest.ex000066400000000000000000000002631254730255300273370ustar00rootroot00000000000000defmodule Escripttest do def start do :ok = Application.start(:escripttest) end def main(_args) do IO.puts Application.get_env(:foobar, :value, "TEST") end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/priv/000077500000000000000000000000001254730255300246415ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/priv/hello/000077500000000000000000000000001254730255300257445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/priv/hello/world.txt000066400000000000000000000000131254730255300276260ustar00rootroot00000000000000Hello Worldelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/src/000077500000000000000000000000001254730255300244505ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest/src/escripttest.erl000066400000000000000000000003121254730255300275210ustar00rootroot00000000000000-module(escripttest). -export([start/0, main/1]). start() -> ok = application:start(escripttest). main(_Args) -> {ok, Val} = application:get_env(escripttest, erlval), io:put_chars(Val). elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest_protocols/000077500000000000000000000000001254730255300257655ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest_protocols/lib/000077500000000000000000000000001254730255300265335ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/escripttest_protocols/lib/escripttest.ex000066400000000000000000000001731254730255300314430ustar00rootroot00000000000000defmodule Escripttest do def main([protocol]) do IO.puts Protocol.consolidated?(Module.concat([protocol])) end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/no_mixfile/000077500000000000000000000000001254730255300234415ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/no_mixfile/lib/000077500000000000000000000000001254730255300242075ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/no_mixfile/lib/a.ex000066400000000000000000000000251254730255300247620ustar00rootroot00000000000000defmodule A do endelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/no_mixfile/lib/b.ex000066400000000000000000000000251254730255300247630ustar00rootroot00000000000000defmodule B do endelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/no_mixfile/lib/c.ex000066400000000000000000000000251254730255300247640ustar00rootroot00000000000000defmodule C do endelixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/only_deps/000077500000000000000000000000001254730255300233045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/only_deps/mix.exs000066400000000000000000000003111254730255300246150ustar00rootroot00000000000000defmodule OnlyDeps.Mix do use Mix.Project def project do [app: :only_deps, version: "0.1.0", deps: [{:git_repo, git: MixTest.Case.fixture_path("git_repo"), only: :other_env}] ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/000077500000000000000000000000001254730255300232335ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/000077500000000000000000000000001254730255300241765ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/rebar_dep/000077500000000000000000000000001254730255300261215ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/rebar_dep/rebar.config000066400000000000000000000000421254730255300303770ustar00rootroot00000000000000{sub_dirs, ["from_apps_another"]}.elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/rebar_dep/src/000077500000000000000000000000001254730255300267105ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/rebar_dep/src/rebar_dep.app.src000066400000000000000000000000661254730255300321250ustar00rootroot00000000000000{application, rebar_dep, [ {vsn, "0.1.0"} ]}. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/apps/rebar_dep/src/rebar_dep.erl000066400000000000000000000001141254730255300313330ustar00rootroot00000000000000-module(rebar_dep). -export ([any_function/0]). any_function() -> ok. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/rebar.config000066400000000000000000000001601254730255300255120ustar00rootroot00000000000000{sub_dirs, ["apps/*"]}. {deps, [ {git_rebar, "0.1..*", {git, "../../test/fixtures/git_rebar", master}} ]}. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep/rebar.config.script000066400000000000000000000000401254730255300270120ustar00rootroot00000000000000CONFIG ++ [{'SCRIPT', SCRIPT}]. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep_script/000077500000000000000000000000001254730255300246175ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep_script/rebar.config000066400000000000000000000000001254730255300270670ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/rebar_dep_script/rebar.config.script000066400000000000000000000000331254730255300304000ustar00rootroot00000000000000[{'dir', file:get_cwd()}]. elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/000077500000000000000000000000001254730255300237435ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/000077500000000000000000000000001254730255300246765ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/000077500000000000000000000000001254730255300265015ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/000077500000000000000000000000001254730255300274445ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/000077500000000000000000000000001254730255300302105ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/lib/000077500000000000000000000000001254730255300307565ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/lib/bar.ex000066400000000000000000000000721254730255300320570ustar00rootroot00000000000000defmodule Bar do def bar do "hello world" end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/mix.exs000066400000000000000000000003041254730255300315230ustar00rootroot00000000000000defmodule Bar.Mix do use Mix.Project def project do Mix.shell.info ":bar env is #{Mix.env}" [ app: :bar, version: "0.1.0", deps: [ {:foo, in_umbrella: true} ] ] end end dont_error_on_files000066400000000000000000000000001254730255300333310ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/appselixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/000077500000000000000000000000001254730255300302275ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/lib/000077500000000000000000000000001254730255300307755ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/lib/foo.ex000066400000000000000000000000701254730255300321130ustar00rootroot00000000000000defmodule Foo do def foo do "bye world" end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/mix.exs000066400000000000000000000002311254730255300315410ustar00rootroot00000000000000defmodule Foo.Mix do use Mix.Project def project do Mix.shell.info ":foo env is #{Mix.env}" [ app: :foo, version: "0.1.0" ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/mix.exs000066400000000000000000000001461254730255300300200ustar00rootroot00000000000000defmodule Umbrella.Mixfile do use Mix.Project def project do [ apps_path: "apps" ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/fixtures/umbrella_dep/mix.exs000066400000000000000000000002751254730255300252650ustar00rootroot00000000000000defmodule UmbrellaDep.Mixfile do use Mix.Project def project do [ app: :umbrella_dep, deps: deps ] end defp deps do [ {:umbrella, path: "deps/umbrella"} ] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/000077500000000000000000000000001254730255300202345ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/aliases_test.exs000066400000000000000000000026061254730255300234410ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.AliasesTest do use MixTest.Case defmodule Aliases do def project do [aliases: [h: "hello", p: &inspect/1, compile: "hello", help: ["help", "hello"], "nested.h": [&Mix.shell.info(inspect(&1)), "h foo bar"]]] end end setup do Mix.Project.push Aliases :ok end test "runs string aliases" do assert Mix.Task.run("h", []) == "Hello, World!" assert Mix.Task.run("h", []) == :noop assert Mix.Task.run("hello", []) == :noop Mix.Task.reenable "h" Mix.Task.reenable "hello" assert Mix.Task.run("h", ["foo", "bar"]) == "Hello, foo bar!" end test "runs function aliases" do assert Mix.Task.run("p", []) == "[]" assert Mix.Task.run("p", []) == :noop Mix.Task.reenable "p" assert Mix.Task.run("p", ["foo", "bar"]) == "[\"foo\", \"bar\"]" end test "runs list aliases" do assert Mix.Task.run("nested.h", ["baz"]) == "Hello, foo bar baz!" assert_received {:mix_shell, :info, ["[]"]} end test "run alias override" do assert Mix.Task.run("compile", []) == "Hello, World!" assert Mix.Task.run("compile", []) == :noop end test "run alias override with recursion" do assert Mix.Task.run("help", []) == "Hello, World!" assert_received {:mix_shell, :info, ["mix test" <> _]} end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/archive_test.exs000066400000000000000000000013761254730255300234440ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.ArchiveTest do use MixTest.Case doctest Mix.Archive test "archive" do in_fixture "archive", fn -> File.write ".elixir", "~> 1.0.0" Mix.Archive.create(".", "sample.ez") archive = 'sample.ez' assert File.exists?(archive) assert has_zip_file?(archive, 'sample/.elixir') assert has_zip_file?(archive, 'sample/priv/not_really_an.so') assert has_zip_file?(archive, 'sample/ebin/Elixir.Mix.Tasks.Local.Sample.beam') assert has_zip_file?(archive, 'sample/ebin/local_sample.app') end end defp has_zip_file?(archive, name) do {:ok, files} = :zip.list_dir(archive) Enum.find(files, &match?({:zip_file, ^name, _, _, _, _}, &1)) end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/cli_test.exs000066400000000000000000000067041254730255300225720ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.CLITest do use MixTest.Case test "default task" do in_fixture "no_mixfile", fn -> File.write! "mix.exs", """ defmodule P do use Mix.Project def project, do: [app: :p, version: "0.1.0"] end """ output = mix ~w[] assert File.regular?("_build/dev/lib/p/ebin/Elixir.A.beam") assert output =~ "Compiled lib/a.ex" end end test "compiles and invokes simple task from CLI" do in_fixture "no_mixfile", fn -> File.mkdir_p!("lib") File.write! "mix.exs", """ defmodule MyProject do use Mix.Project def project do [app: :my_project, version: "0.0.1"] end def hello_world do "Hello from MyProject!" end end """ File.write! "lib/hello.ex", """ defmodule Mix.Tasks.Hello do use Mix.Task @shortdoc "Hello" def run(_) do IO.puts Mix.Project.get!.hello_world end end """ contents = mix ~w[hello] assert contents =~ "Hello from MyProject!\n" assert contents =~ "Compiled lib/hello.ex\n" end end test "no task error" do in_fixture "no_mixfile", fn -> contents = mix ~w[no_task] assert contents =~ "** (Mix) The task no_task could not be found" end end test "--help smoke test" do in_fixture "no_mixfile", fn -> output = mix ~w[--help] assert output =~ ~r/mix compile\s+# Compile source files/ refute output =~ "mix invalid" end end test "--version smoke test" do in_fixture "no_mixfile", fn -> output = mix ~w[--version] assert output =~ ~r/Mix [0-9\.a-z]+/ end end test "env config" do in_fixture "no_mixfile", fn -> File.write! "custom.exs", """ defmodule P do use Mix.Project def project, do: [app: :p, version: "0.1.0"] end """ System.put_env("MIX_ENV", "prod") System.put_env("MIX_EXS", "custom.exs") output = mix ["run", "-e", "IO.inspect {Mix.env, System.argv}", "--", "1", "2", "3"] assert output =~ "Compiled lib/a.ex" assert output =~ ~s({:prod, ["1", "2", "3"]}) end after System.delete_env("MIX_ENV") System.delete_env("MIX_EXS") end test "new with tests" do in_tmp "new_with_tests", fn -> output = mix ~w[new .] assert output =~ "* creating lib/new_with_tests.ex" output = mix ~w[test test/new_with_tests_test.exs --cover] assert File.regular?("_build/test/lib/new_with_tests/ebin/Elixir.NewWithTests.beam") assert output =~ "1 test, 0 failures" assert output =~ "Generating cover results ..." assert File.regular?("cover/Elixir.NewWithTests.html") end end test "new --sup with tests" do in_tmp "sup_with_tests", fn -> output = mix ~w[new --sup .] assert output =~ "* creating lib/sup_with_tests.ex" output = mix ~w[test] assert File.regular?("_build/test/lib/sup_with_tests/ebin/Elixir.SupWithTests.beam") assert output =~ "1 test, 0 failures" end end defp mix(args) when is_list(args) do System.cmd(elixir_executable, ["-r", mix_executable, "--"|args], [stderr_to_stdout: true]) |> elem(0) end defp mix_executable do Path.expand("../../../../bin/mix", __DIR__) end defp elixir_executable do Path.expand("../../../../bin/elixir", __DIR__) end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/config_test.exs000066400000000000000000000075611254730255300232720ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.ConfigTest do use MixTest.Case, async: true doctest Mix.Config defmacrop config do quote do Mix.Config.Agent.get(var!(config_agent, Mix.Config)) end end test "config/2" do use Mix.Config assert config() == [] config :lager, key: :value assert config() == [lager: [key: :value]] config :lager, other: :value assert config() == [lager: [key: :value, other: :value]] config :lager, key: :other assert config() == [lager: [key: :other, other: :value]] # Works inside functions too... f = fn -> config(:lager, key: :fn) end f.() assert config() == [lager: [key: :fn, other: :value]] # ...and in for comprehensions. for _ <- 0..0, do: config(:lager, key: :for) assert config() == [lager: [key: :for, other: :value]] end test "config/3" do use Mix.Config config :app, Repo, key: :value assert config() == [app: [{Repo, key: :value}]] config :app, Repo, other: :value assert config() == [app: [{Repo, key: :value, other: :value}]] config :app, Repo, key: :other assert config() == [app: [{Repo, key: :other, other: :value}]] config :app, Repo, key: [nested: false] assert config() == [app: [{Repo, key: [nested: false], other: :value}]] config :app, Repo, key: [nested: true] assert config() == [app: [{Repo, key: [nested: true], other: :value}]] config :app, Repo, key: :other assert config() == [app: [{Repo, key: :other, other: :value}]] end test "import_config/1" do use Mix.Config import_config fixture_path("configs/good_config.exs") assert config() == [my_app: [key: :value]] end test "import_config/1 with wildcards" do use Mix.Config import_config fixture_path("configs/good_*.exs") assert config() == [my_app: [key: :value]] end test "import_config/1 with wildcard with no matches" do use Mix.Config import_config fixture_path("configs/nonexistent_*.exs") assert config() == [] end test "import_config/1 with nested" do use Mix.Config config :app, Repo, key: [nested: false, other: true] import_config fixture_path("configs/nested.exs") assert config() == [app: [{Repo, key: [nested: true, other: true]}]] end test "import_config/1 with bad path" do use Mix.Config assert_raise Mix.Config.LoadError, ~r"could not load config", fn -> import_config fixture_path("configs/unknown.exs") end end test "read!/1" do assert Mix.Config.read!(fixture_path("configs/good_config.exs")) == [my_app: [key: :value]] assert Mix.Config.read!(fixture_path("configs/good_import.exs")) == [my_app: [key: :value]] exception = assert_raise Mix.Config.LoadError, fn -> Mix.Config.read! fixture_path("configs/bad_app.exs") end assert Exception.message(exception) =~ ~r"could not load config .*bad_app\.exs\n" assert Exception.message(exception) =~ ~r"expected config for app :sample to return keyword list, got: :oops" exception = assert_raise Mix.Config.LoadError, fn -> Mix.Config.read! fixture_path("configs/bad_root.exs") end assert Exception.message(exception) =~ ~r"could not load config .*bad_root\.exs\n" assert Exception.message(exception) =~ ~r"expected config file to return keyword list, got: :oops" exception = assert_raise Mix.Config.LoadError, fn -> Mix.Config.read! fixture_path("configs/bad_import.exs") end assert Exception.message(exception) =~ ~r"could not load config .*bad_root\.exs\n" assert Exception.message(exception) =~ ~r"expected config file to return keyword list, got: :oops" end test "persist/1" do assert Application.get_env(:my_app, :key) == nil Mix.Config.persist [my_app: [key: :value]] assert Application.get_env(:my_app, :key) == :value after Application.delete_env(:my_app, :key) end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/dep/000077500000000000000000000000001254730255300210045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/dep/lock_test.exs000066400000000000000000000016671254730255300235260ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Dep.LockTest do use MixTest.Case setup do Mix.Project.push MixTest.Case.Sample :ok end test "creates new lock and manifest files" do in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{foo: :bar} assert File.regular? "mix.lock" assert File.regular? "_build/dev/lib/sample/.compile.lock" end end test "does not touch manifest file there is no change" do in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{foo: :bar, bar: :bat} File.rm! "_build/dev/lib/sample/.compile.lock" Mix.Dep.Lock.write %{bar: :bat, foo: :bar} refute File.regular? "_build/dev/lib/sample/.compile.lock" end end test "stores version in manifest" do in_fixture "no_mixfile", fn -> assert is_nil Mix.Dep.Lock.elixir_vsn Mix.Dep.Lock.touch assert Mix.Dep.Lock.elixir_vsn == System.version end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/dep_test.exs000066400000000000000000000164151254730255300225730ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.DepTest do use MixTest.Case defmodule DepsApp do def project do [ deps: [ {:ok, "0.1.0", path: "deps/ok"}, {:invalidvsn, "0.2.0", path: "deps/invalidvsn"}, {:invalidapp, "0.1.0", path: "deps/invalidapp"}, {:noappfile, "0.1.0", path: "deps/noappfile"}, {:uncloned, git: "https://github.com/elixir-lang/uncloned.git"}, {:optional, git: "https://github.com/elixir-lang/optional.git", optional: true} ] ] end end defmodule MixVersionApp do def project do [ deps: [ {:ok, "~> 0.1", path: "deps/ok"} ] ] end end defmodule NoSCMApp do def project do [ deps: [ { :ok, "~> 0.1", not_really: :ok } ] ] end end defmodule InvalidDepsReq do def project do [ deps: [ {:ok, "+- 0.1.0", path: "deps/ok"} ] ] end end test "extracts all dependencies from the given project" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> deps = Mix.Dep.loaded([]) assert length(deps) == 6 assert Enum.find deps, &match?(%Mix.Dep{app: :ok, status: {:ok, _}}, &1) assert Enum.find deps, &match?(%Mix.Dep{app: :invalidvsn, status: {:invalidvsn, :ok}}, &1) assert Enum.find deps, &match?(%Mix.Dep{app: :invalidapp, status: {:invalidapp, _}}, &1) assert Enum.find deps, &match?(%Mix.Dep{app: :noappfile, status: {:noappfile, _}}, &1) assert Enum.find deps, &match?(%Mix.Dep{app: :uncloned, status: {:unavailable, _}}, &1) assert Enum.find deps, &match?(%Mix.Dep{app: :optional, status: {:unavailable, _}}, &1) end end test "use requirements for dependencies" do Mix.Project.push MixVersionApp in_fixture "deps_status", fn -> deps = Mix.Dep.loaded([]) assert Enum.find deps, &match?(%Mix.Dep{app: :ok, status: {:ok, _}}, &1) end end test "raises when no SCM is specified" do Mix.Project.push NoSCMApp in_fixture "deps_status", fn -> send self, {:mix_shell_input, :yes?, false} msg = "Could not find a SCM for dependency :ok from Mix.DepTest.NoSCMApp" assert_raise Mix.Error, msg, fn -> Mix.Dep.loaded([]) end end end test "does not set the manager before the dependency was loaded" do # It is important to not eagerly set the manager because the dependency # needs to be loaded (i.e. available in the filesystem) in order to get # the proper manager. Mix.Project.push DepsApp {_, true, _} = Mix.Dep.Converger.converge(false, [], nil, fn dep, acc, lock -> assert is_nil(dep.manager) {dep, acc or true, lock} end) end test "raises on invalid deps req" do Mix.Project.push InvalidDepsReq in_fixture "deps_status", fn -> assert_raise Mix.Error, ~r"Invalid requirement", fn -> Mix.Dep.loaded([]) end end end defmodule NestedDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:deps_repo, "0.1.0", path: "custom/deps_repo"} ] ] end end test "nested deps come first" do Mix.Project.push NestedDepsApp in_fixture "deps_status", fn -> assert Enum.map(Mix.Dep.loaded([]), &(&1.app)) == [:git_repo, :deps_repo] end end test "nested optional deps are never added" do Mix.Project.push NestedDepsApp in_fixture "deps_status", fn -> File.write! "custom/deps_repo/mix.exs", """ defmodule DepsRepo do use Mix.Project def project do [ app: :deps_repo, version: "0.1.0", deps: [ {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), optional: true} ] ] end end """ assert Enum.map(Mix.Dep.loaded([]), &(&1.app)) == [:deps_repo] end end defmodule ConvergedDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:deps_repo, "0.1.0", path: "custom/deps_repo"}, {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end test "correctly order converged deps" do Mix.Project.push ConvergedDepsApp in_fixture "deps_status", fn -> assert Enum.map(Mix.Dep.loaded([]), &(&1.app)) == [:git_repo, :deps_repo] end end test "correctly order converged deps even with optional dependencies" do Mix.Project.push ConvergedDepsApp in_fixture "deps_status", fn -> File.write! "custom/deps_repo/mix.exs", """ defmodule DepsRepo do use Mix.Project def project do [ app: :deps_repo, version: "0.1.0", deps: [ {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), optional: true} ] ] end end """ assert Enum.map(Mix.Dep.loaded([]), &(&1.app)) == [:git_repo, :deps_repo] end end defmodule IdentityRemoteConverger do @behaviour Mix.RemoteConverger def remote?(_app), do: true def converge(_deps, lock) do Process.put(:remote_converger, true) lock end def deps(_deps, _lock) do [] end end test "remote converger" do Mix.Project.push ConvergedDepsApp Mix.RemoteConverger.register(IdentityRemoteConverger) in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run([]) message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} assert Process.get(:remote_converger) end after Mix.RemoteConverger.register(nil) end defmodule OnlyDeps do def project do [ deps: [ {:foo, github: "elixir-lang/foo"}, {:bar, github: "elixir-lang/bar", only: :other_env} ] ] end end test "only extract deps matching environment" do Mix.Project.push OnlyDeps in_fixture "deps_status", fn -> deps = Mix.Dep.loaded([env: :other_env]) assert length(deps) == 2 deps = Mix.Dep.loaded([]) assert length(deps) == 2 deps = Mix.Dep.loaded([env: :prod]) assert length(deps) == 1 assert Enum.find deps, &match?(%Mix.Dep{app: :foo}, &1) end end defmodule OnlyChildDeps do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:only_deps, path: fixture_path("only_deps")} ] ] end end test "only fetch child deps matching prod env" do Mix.Project.push OnlyChildDeps in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run([]) message = "* Getting git_repo (#{fixture_path("git_repo")})" refute_received {:mix_shell, :info, [^message]} end end defmodule OnlyParentDeps do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:only, github: "elixir-lang/only", only: :dev} ] ] end end test "only fetch parent deps matching specified env" do Mix.Project.push OnlyParentDeps in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run(["--only", "prod"]) refute_received {:mix_shell, :info, ["* Getting" <> _]} assert_raise Mix.Error, "Can't continue due to errors on dependencies", fn -> Mix.Tasks.Deps.Check.run([]) end Mix.env(:prod) Mix.Tasks.Deps.Check.run([]) end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/generator_test.exs000066400000000000000000000031771254730255300240120ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.GeneratorTest do use MixTest.Case import Mix.Generator embed_text :foo, "foo" embed_text :self, from_file: __ENV__.file embed_template :bar, "<%= @a + @b %>" test :embed_text do assert foo_text == "foo" end test :embed_template do assert bar_template(a: 1, b: 2) == "3" end test :from_file do assert self_text =~ "import Mix.Generator" end test :create_file do in_tmp "create_file", fn -> create_file "foo", "HELLO" assert File.read!("foo") == "HELLO" assert_received {:mix_shell, :info, ["* creating foo"]} end end test :force_create_file do in_tmp "create_file", fn -> File.write! "foo", "HELLO" create_file "foo", "WORLD", force: true assert File.read!("foo") == "WORLD" refute_received {:mix_shell, :yes?, ["foo already exists, overwrite?"]} assert_received {:mix_shell, :info, ["* creating foo"]} end end test :create_with_conflict_returning_true do in_tmp "create_file", fn -> File.write! "foo", "HELLO" send self, {:mix_shell_input, :yes?, true} create_file "foo", "WORLD" assert File.read!("foo") == "WORLD" assert_received {:mix_shell, :yes?, ["foo already exists, overwrite?"]} end end test :create_with_conflict_returning_false do in_tmp "create_file", fn -> File.write! "foo", "HELLO" send self, {:mix_shell_input, :yes?, false} create_file "foo", "WORLD" assert File.read!("foo") == "HELLO" assert_received {:mix_shell, :yes?, ["foo already exists, overwrite?"]} end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/project_test.exs000066400000000000000000000104441254730255300234650ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.ProjectTest do use MixTest.Case defmodule SampleProject do def project do [app: :sample, hello: "world"] end end test "push and pop projects" do refute Mix.Project.get Mix.Project.push(SampleProject, "sample") assert Mix.Project.get == SampleProject assert %{name: SampleProject, config: _, file: "sample"} = Mix.Project.pop assert nil = Mix.Project.pop end test "does not allow the same project to be pushed twice" do Mix.Project.push(SampleProject, "sample") assert_raise Mix.Error, ~r/Mix.ProjectTest.SampleProject from "another"/, fn -> Mix.Project.push(SampleProject, "another") end end test "allows nil projects to be pushed twice" do Mix.Project.push nil Mix.Project.push nil assert is_map Mix.Project.pop assert is_map Mix.Project.pop assert is_nil Mix.Project.pop end test "retrieves configuration from projects" do Mix.Project.push(SampleProject) assert Mix.Project.config[:hello] == "world" end test "removes private configuration" do Mix.Project.push(SampleProject) assert is_nil Mix.Project.config[:app_path] end test "retrieves configuration even when a project is not set" do assert Mix.Project.config[:default_task] == "run" end test "raises an error when trying to retrieve the current project but none is set" do assert_raise Mix.NoProjectError, fn -> Mix.Project.get! end end test "builds the project structure" do in_fixture "archive", fn -> config = [app_path: Path.expand("_build/archive")] assert Mix.Project.build_structure(config) == :ok assert File.dir?("_build/archive/ebin") assert_proj_dir_linked_or_copied("_build/archive/priv", "priv", '../../priv') end end test "builds the project structure without symlinks" do in_fixture "archive", fn -> config = [app_path: Path.expand("_build/archive"), build_embedded: true] assert Mix.Project.build_structure(config) == :ok assert File.dir?("_build/archive/ebin") assert {:error, _} = :file.read_link("_build/archive/ebin") end end test "builds the project structure with symlinks" do in_fixture "archive", fn -> config = [app_path: Path.expand("_build/archive")] File.mkdir_p!("include") assert Mix.Project.build_structure(config, symlink_ebin: true) == :ok assert_proj_dir_linked_or_copied("_build/archive/ebin", "ebin", '../../ebin') assert_proj_dir_linked_or_copied("_build/archive/priv", "priv", '../../priv') assert_proj_dir_linked_or_copied("_build/archive/include", "include", '../../include') assert Mix.Project.build_structure(config) == :ok assert File.dir?("_build/archive/ebin") assert_proj_dir_linked_or_copied("_build/archive/priv", "priv", '../../priv') end end test "in_project pushes given configuration" do in_fixture "no_mixfile", fn -> Mix.Project.in_project :foo, ".", [hello: :world], fn _ -> assert Mix.Project.config[:app] == :foo assert Mix.Project.config[:hello] == :world end end end test "in_project prints nice error message if fails to load file" do in_fixture "no_mixfile", fn -> File.write "mix.exs", """ raise "oops" """ assert_raise RuntimeError, "oops", fn -> Mix.Project.in_project :hello, ".", [], fn _ -> :ok end end assert_receive {:mix_shell, :error, ["Error while loading project :hello at" <> _]} end end test "config_files" do Mix.Project.push(SampleProject) in_fixture "no_mixfile", fn -> File.mkdir_p!("config/sub") File.write! "config/config.exs", "[]" File.write! "config/dev.exs", "[]" File.write! "config/.exs", "[]" File.write! "config/sub/init.exs", "[]" files = Mix.Project.config_files assert __ENV__.file in files assert "config/config.exs" in files assert "config/dev.exs" in files refute "config/.exs" in files assert "config/sub/init.exs" in files end end defp assert_proj_dir_linked_or_copied(source, target, symlink_path) do case :file.read_link(source) do {:ok, path} -> assert path == symlink_path {:error, _} -> assert File.ls!(source) == File.ls!(target) end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/rebar_test.exs000066400000000000000000000110021254730255300231010ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.RebarTest do use MixTest.Case defmodule RebarAsDep do def project do [ app: :rebar_as_dep, version: "0.1.0", deps: [ {:rebar_dep, path: MixTest.Case.tmp_path("rebar_dep"), app: false} ] ] end end test "load rebar config" do path = MixTest.Case.fixture_path("rebar_dep") config = Mix.Rebar.load_config(path) assert config[:sub_dirs] == ['apps/*'] assert config[:SCRIPT] == 'rebar.config.script' end test "execute rebar.config.script on dependency directory" do path = MixTest.Case.fixture_path("rebar_dep_script") config = Mix.Rebar.load_config(path) assert config[:dir] == {:ok, String.to_char_list(path)} end test "parse rebar dependencies" do config = [deps: [{:git_rebar, '.*',}]] assert [{:git_rebar, ~r".*", [path: "deps/git_rebar"]}] == Mix.Rebar.deps(config) config = [deps: [{:git_rebar, '.*',}], deps_dir: "other_dir"] assert [{:git_rebar, ~r".*", [path: "other_dir/git_rebar"]}] == Mix.Rebar.deps(config) config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar', :master}}]] assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", ref: "master"]}] == Mix.Rebar.deps(config) config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar'}, [:raw]}]] assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", compile: false]}] == Mix.Rebar.deps(config) config = [deps: [{:git_rebar, '', {:git, '../../test/fixtures/git_rebar', {:ref, '64691eb'}}}]] assert [{:git_rebar, ~r"", [git: "../../test/fixtures/git_rebar", ref: "64691eb"]}] == Mix.Rebar.deps(config) end test "parse rebar dependencies from rebar.config" do Mix.Project.push(RebarAsDep) deps = Mix.Dep.loaded([]) assert Enum.find(deps, &match?(%Mix.Dep{app: :rebar_dep}, &1)) assert Enum.find(deps, fn %Mix.Dep{app: app, opts: opts} -> if app == :git_rebar do assert Enum.find(opts, &match?({:git, "../../test/fixtures/git_rebar"}, &1)) assert Enum.find(opts, &match?({:ref, "master"}, &1)) true end end) end test "recurs over sub dirs" do path = MixTest.Case.fixture_path("rebar_dep") File.cd! path, fn -> config = Mix.Rebar.load_config(path) Mix.Rebar.recur(config, fn config -> if config[:sub_dirs] == ['from_apps_another'] do Process.put(:inside_apps_another, true) end end) end unless Process.get(:inside_apps_another) do flunk "Expected inside_apps_another to return true" end end test "get and compile dependencies for rebar" do Mix.Project.push(RebarAsDep) in_tmp "get and compile dependencies for rebar", fn -> Mix.Tasks.Deps.Get.run [] assert_received {:mix_shell, :info, ["* Getting git_rebar (../../test/fixtures/git_rebar)"]} Mix.Tasks.Deps.Compile.run [] assert_received {:mix_shell, :run, ["==> git_rebar (compile)\n"]} assert_received {:mix_shell, :run, ["==> rebar_dep (compile)\n"]} assert :git_rebar.any_function == :ok assert :rebar_dep.any_function == :ok load_paths = Mix.Dep.loaded([]) |> Enum.map(&Mix.Dep.load_paths(&1)) |> Enum.concat assert File.exists?("_build/dev/lib/rebar_dep/ebin/rebar_dep.beam") assert File.exists?("_build/dev/lib/git_rebar/ebin/git_rebar.beam") # Assert we have no .compile.lock as a .compile.lock # means we check for the Elixir version on every command. refute File.exists?("_build/dev/lib/rebar_dep/.compile.lock") refute File.exists?("_build/dev/lib/git_rebar/.compile.lock") assert Enum.any?(load_paths, &String.ends_with?(&1, "git_rebar/ebin")) assert Enum.any?(load_paths, &String.ends_with?(&1, "rebar_dep/ebin")) end end test "get and compile dependencies for rebar with mix" do Mix.Project.push(RebarAsDep) in_tmp "get and compile dependencies for rebar with mix", fn -> File.write! MixTest.Case.tmp_path("rebar_dep/mix.exs"), """ defmodule RebarDep.Mixfile do use Mix.Project def project do [app: :rebar_dep, version: "0.0.1"] end end """ Mix.Tasks.Deps.Compile.run [] assert_received {:mix_shell, :info, ["==> rebar_dep"]} assert_received {:mix_shell, :info, ["Generated rebar_dep app"]} end after File.rm MixTest.Case.tmp_path("rebar_dep/mix.exs") end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/scm/000077500000000000000000000000001254730255300210165ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/scm/git_test.exs000066400000000000000000000033761254730255300233720ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.SCM.GitTest do use MixTest.Case, async: true test "formats the lock" do assert Mix.SCM.Git.format_lock(lock()) == "abcdef0" assert Mix.SCM.Git.format_lock(lock(branch: "master")) == "abcdef0 (branch: master)" assert Mix.SCM.Git.format_lock(lock(tag: "v0.12.0")) == "abcdef0 (tag: v0.12.0)" assert Mix.SCM.Git.format_lock(lock(ref: "abcdef0")) == "abcdef0 (ref)" end test "considers two dep equals if the have the same git and the same opts" do assert Mix.SCM.Git.equal?([git: "foo"], [git: "foo"]) refute Mix.SCM.Git.equal?([git: "foo"], [git: "bar"]) assert Mix.SCM.Git.equal?([git: "foo", branch: "master"], [git: "foo", branch: "master"]) refute Mix.SCM.Git.equal?([git: "foo", branch: "master"], [git: "foo", branch: "other"]) end # TODO: remove this in Elixir v2.0 when this functionality is removed test "considers two GitHub dep equals if they are the same repo and opts match, just different protocols" do git_url = "git://github.com/elixir-lang/elixir.git" https_url = "https://github.com/elixir-lang/elixir.git" assert Mix.SCM.Git.equal?([git: git_url], [git: https_url]) refute Mix.SCM.Git.equal?([git: "git@github.com:elixir-lang/ecto.git"], [git: https_url]) assert Mix.SCM.Git.equal?([git: git_url, branch: "master"], [git: https_url, branch: "master"]) refute Mix.SCM.Git.equal?([git: git_url, branch: "master"], [git: https_url, branch: "other"]) end test "lock should not be taken into account when considering deps equal as the lock is shared" do assert Mix.SCM.Git.equal?([git: "foo", lock: 1], [git: "foo", lock: 2]) end defp lock(opts \\ []) do [lock: {:git, "/repo", "abcdef0123456789", opts}] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/scm_test.exs000066400000000000000000000006571254730255300226060ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.SCMTest do use MixTest.Case setup do available = Mix.SCM.available on_exit fn -> Mix.State.put(:scm, available) end :ok end test "prepends a SCM" do Mix.SCM.prepend(Hello) assert Enum.at(Mix.SCM.available, 0) == Hello end test "appends a SCM" do Mix.SCM.append(Hello) assert Enum.at(Mix.SCM.available, -1) == Hello end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/shell/000077500000000000000000000000001254730255300213435ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/shell/io_test.exs000066400000000000000000000024401254730255300235320ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Shell.IOTest do use MixTest.Case import ExUnit.CaptureIO import Mix.Shell.IO test "prints info message to stdio" do assert capture_io(fn -> info "hello" end) == "hello\n" end test "prints error message to stderr" do assert capture_io(:stderr, fn -> error "hello" end) =~ "hello" end test "asks the user with yes?" do assert capture_io("\n", fn -> yes?("Ok?") end) == "Ok? [Yn] " assert capture_io("\n", fn -> assert yes?("Ok?") end) assert capture_io("Yes", fn -> assert yes?("Ok?") end) assert capture_io("yes", fn -> assert yes?("Ok?") end) assert capture_io("y", fn -> assert yes?("Ok?") end) assert capture_io("n", fn -> refute yes?("Ok?") end) assert capture_io("", fn -> refute yes?("Ok?") end) end test "runs a given command" do assert capture_io("", fn -> assert cmd("echo hello") == 0 end) == "hello\n" will_print_sample() assert capture_io("", fn -> assert cmd("echo hello", print_app: false) == 0 end) == "hello\n" assert capture_io("", fn -> assert cmd("echo hello") == 0 end) == "==> sample\nhello\n" end defp will_print_sample do Mix.Project.push nil Mix.Project.push MixTest.Case.Sample end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/shell_test.exs000066400000000000000000000041641254730255300231300ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.ShellTest do use MixTest.Case defp capture_io(somefunc) do ExUnit.CaptureIO.capture_io(somefunc) |> String.replace("\r\n","\n") end defp capture_io(from, somefunc) do ExUnit.CaptureIO.capture_io(from, somefunc) |> String.replace("\r\n","\n") end setup do on_exit fn -> Mix.shell(Mix.Shell.Process) end :ok end test "shell process" do Mix.shell.info "abc" Mix.shell.error "def" assert_received {:mix_shell, :info, ["abc"]} assert_received {:mix_shell, :error, ["def"]} send self, {:mix_shell_input, :prompt, "world"} assert Mix.shell.prompt("hello?") == "world" assert_received {:mix_shell, :prompt, ["hello?"]} send self, {:mix_shell_input, :yes?, true} assert Mix.shell.yes?("hello?") assert_received {:mix_shell, :yes?, ["hello?"]} assert Mix.shell.cmd("echo first") == 0 nl = os_newline assert_received {:mix_shell, :run, ["first" <> ^nl]} end test "shell io" do Mix.shell Mix.Shell.IO assert capture_io(fn -> Mix.shell.info "abc" end) == "abc\n" if IO.ANSI.enabled? do assert capture_io(:stderr, fn -> Mix.shell.error "def" end) == "#{IO.ANSI.red}#{IO.ANSI.bright}def#{IO.ANSI.reset}\n" else assert capture_io(:stderr, fn -> Mix.shell.error "def" end) == "def\n" end assert capture_io("world", fn -> assert Mix.shell.prompt("hello?") == "world" end) == "hello? " assert capture_io("Yes", fn -> assert Mix.shell.yes?("hello?") end) == "hello? [Yn] " assert capture_io(fn -> assert Mix.shell.cmd("echo first") == 0 end) == "first\n" end test "shell cmd supports expressions" do Mix.shell Mix.Shell.IO assert (capture_io(fn -> assert Mix.shell.cmd("echo first && echo second") == 0 end) |> String.replace(" \n", "\n")) == "first\nsecond\n" end test "shell cmd ignores output if desired" do Mix.shell Mix.Shell.IO assert capture_io(fn -> assert Mix.shell.cmd("echo first && echo second", quiet: true) == 0 end) == "" end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/task_test.exs000066400000000000000000000061321254730255300227600ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.TaskTest do use MixTest.Case defmodule SampleProject do def project do [app: :sample, version: "0.0.1"] end end test "run/1" do assert Mix.Task.run("hello") == "Hello, World!" assert Mix.Task.run("hello") == :noop assert_raise Mix.NoTaskError, "The task unknown could not be found", fn -> Mix.Task.run("unknown") end assert_raise Mix.NoTaskError, "The task helli could not be found. Did you mean 'hello'?", fn -> Mix.Task.run("helli") end assert_raise Mix.InvalidTaskError, "The task invalid does not export run/1", fn -> Mix.Task.run("invalid") end end test "try to compile if task is missing" do in_fixture "no_mixfile", fn -> Mix.Project.push(SampleProject, "sample") assert_raise Mix.NoTaskError, fn -> Mix.Task.run("unknown") end # Check if compile task have run refute Mix.TasksServer.run({:task, "compile", Mix.Project.get}) end end test "does not try to compile if task is missing in build embedded" do in_fixture "no_mixfile", fn -> Mix.ProjectStack.post_config(build_embedded: true) Mix.Project.push(SampleProject, "sample") assert_raise Mix.Error, ~r/Cannot execute task because the project was not yet compiled/, fn -> Mix.Task.run("unknown") end end end test "clear/0" do assert Mix.Task.run("hello") == "Hello, World!" Mix.Task.clear assert Mix.Task.run("hello") == "Hello, World!" end test "reenable/1" do assert Mix.Task.run("hello") == "Hello, World!" Mix.Task.reenable("hello") assert Mix.Task.run("hello") == "Hello, World!" end test "reenable/1 for umbrella" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project(:umbrella, ".", fn _ -> assert [:ok, :ok] = Mix.Task.run "clean" assert :noop = Mix.Task.run "clean" Mix.Task.reenable "clean" assert [:ok, :ok] = Mix.Task.run "clean" assert :noop = Mix.Task.run "clean" end) end end test "get!" do assert Mix.Task.get!("hello") == Mix.Tasks.Hello assert_raise Mix.NoTaskError, "The task unknown could not be found", fn -> Mix.Task.get!("unknown") end assert_raise Mix.InvalidTaskError, "The task invalid does not export run/1", fn -> Mix.Task.get!("invalid") end end test "alias?/1" do refute Mix.Task.alias?(:sample) refute Mix.Task.alias?("sample") Mix.Project.push MixTest.Case.Sample assert Mix.Task.alias?(:sample) assert Mix.Task.alias?("sample") refute Mix.Task.alias?("another") after Mix.Project.pop end test "all_modules/0" do Mix.Task.load_all modules = Mix.Task.all_modules assert Mix.Tasks.Hello in modules assert Mix.Tasks.Compile in modules end test "moduledoc/1" do Code.prepend_path MixTest.Case.tmp_path("beams") assert Mix.Task.moduledoc(Mix.Tasks.Hello) == "A test task.\n" end test "shortdoc/1" do assert Mix.Task.shortdoc(Mix.Tasks.Hello) == "This is short documentation, see" end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/000077500000000000000000000000001254730255300213615ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/app.start_test.exs000066400000000000000000000154361254730255300250660ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.App.StartTest do use MixTest.Case defmodule AppStartSample do def project do [app: :app_start_sample, version: "0.1.0", start_permanent: true] end def application do [applications: [:logger]] end end defmodule AppEmbeddedSample do def project do [app: :app_embedded_sample, version: "0.1.0", build_embedded: true] end end defmodule WrongElixirProject do def project do [app: :error, version: "0.1.0", elixir: "~> 0.8.1"] end end setup config do if app = config[:app] do Logger.remove_backend(:console) on_exit fn -> Application.stop(app) Application.unload(app) Logger.add_backend(:console, flush: true) end end :ok end test "compiles and starts the project" do Mix.Project.push AppStartSample in_fixture "no_mixfile", fn -> assert_raise Mix.Error, fn -> Mix.Tasks.App.Start.run ["--no-compile"] end Mix.Tasks.App.Start.run ["--no-start"] assert File.regular?("_build/dev/lib/app_start_sample/ebin/Elixir.A.beam") assert File.regular?("_build/dev/lib/app_start_sample/ebin/app_start_sample.app") refute List.keyfind(:application.which_applications, :app_start_sample, 0) refute List.keyfind(:application.which_applications, :logger, 0) Mix.Tasks.App.Start.run [] assert List.keyfind(:application.which_applications, :app_start_sample, 0) assert List.keyfind(:application.which_applications, :logger, 0) end end test "compiles and starts a project with build_embedded" do Mix.Project.push AppEmbeddedSample in_fixture "no_mixfile", fn -> assert_raise Mix.Error, ~r"Cannot execute task because the project was not yet compiled", fn -> Mix.Tasks.App.Start.run [] end Mix.Tasks.Compile.run([]) Mix.Tasks.App.Start.run([]) end end test "validates Elixir version requirement" do Mix.ProjectStack.post_config elixir: "~> ~> 0.8.1" Mix.Project.push WrongElixirProject in_fixture "no_mixfile", fn -> assert_raise Mix.Error, ~r"Invalid Elixir version requirement", fn -> Mix.Tasks.App.Start.run ["--no-start"] end end end test "validates the Elixir version with requirement" do Mix.Project.push WrongElixirProject in_fixture "no_mixfile", fn -> assert_raise Mix.ElixirVersionError, ~r/You're trying to run :error on Elixir/, fn -> Mix.Tasks.App.Start.run ["--no-start"] end end end test "does not validate the Elixir version with requirement when disabled" do Mix.Project.push WrongElixirProject in_fixture "no_mixfile", fn -> Mix.Tasks.App.Start.run ["--no-start", "--no-elixir-version-check"] end end test "start does nothing if app is nil" do assert Mix.Tasks.App.Start.start([app: nil], []) == :ok end test "allows type to be configured" do assert Mix.Tasks.App.Start.type([], [permanent: true]) == :permanent assert Mix.Tasks.App.Start.type([], [temporary: true]) == :temporary assert Mix.Tasks.App.Start.type([start_permanent: true], []) == :permanent assert Mix.Tasks.App.Start.type([], []) == :temporary end defmodule ReturnSample do def project do [app: :return_sample, version: "0.1.0"] end def application do Process.get(:application_definition) end end defmodule ReturnApp do use Application def start(_type, return), do: return end @tag app: :return_sample test "start points to report on error" do Mix.Project.push ReturnSample in_fixture "no_mixfile", fn -> Process.put(:application_definition, mod: {ReturnApp, {:error, :bye}}) Mix.Tasks.Compile.run [] message = "Could not start application return_sample: " <> "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, {:error, :bye}) " <> "returned an error: :bye" assert_raise Mix.Error, message, fn -> Mix.Tasks.App.Start.start([app: :return_sample], []) end end end @tag app: :return_sample test "start points to report on exception error" do Mix.Project.push ReturnSample in_fixture "no_mixfile", fn -> Process.put(:application_definition, mod: {ReturnApp, {:error, {:badarg, [{ReturnApp, :start, 2, []}] }}}) Mix.Tasks.Compile.run [] message = "Could not start application return_sample: " <> "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, {:error, {:badarg, [{Mix.Tasks.App.StartTest.ReturnApp, :start, 2, []}]}}) " <> "returned an error: an exception was raised:\n" <> " ** (ArgumentError) argument error\n" <> " Mix.Tasks.App.StartTest.ReturnApp.start/2" assert_raise Mix.Error, message, fn -> Mix.Tasks.App.Start.start([app: :return_sample], []) end end end @tag app: :return_sample test "start points to report on bad return" do Mix.Project.push ReturnSample in_fixture "no_mixfile", fn -> Process.put(:application_definition, mod: {ReturnApp, :bad}) Mix.Tasks.Compile.run [] message = "Could not start application return_sample: " <> "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, :bad) " <> "returned a bad value: :bad" assert_raise Mix.Error, message, fn -> Mix.Tasks.App.Start.start([app: :return_sample], []) end end end defmodule ExitSample do def project do [app: :exit_sample, version: "0.1.0"] end def application do Process.get(:application_definition) end end defmodule ExitApp do use Application def start(_type, reason), do: exit(reason) end @tag app: :exit_sample test "start points to report on exit" do Mix.Project.push ExitSample in_fixture "no_mixfile", fn -> Process.put(:application_definition, mod: {ExitApp, :bye}) Mix.Tasks.Compile.run [] message = "Could not start application exit_sample: exited in: " <> "Mix.Tasks.App.StartTest.ExitApp.start(:normal, :bye)\n" <> " ** (EXIT) :bye" assert_raise Mix.Error, message, fn -> Mix.Tasks.App.Start.start([app: :exit_sample], []) end end end @tag app: :exit_sample test "start points to report on normal exit" do Mix.Project.push ExitSample in_fixture "no_mixfile", fn -> Process.put(:application_definition, mod: {ExitApp, :normal}) Mix.Tasks.Compile.run [] message = "Could not start application exit_sample: exited in: " <> "Mix.Tasks.App.StartTest.ExitApp.start(:normal, :normal)\n" <> " ** (EXIT) normal" assert_raise Mix.Error, message, fn -> Mix.Tasks.App.Start.start([app: :exit_sample], []) end end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/archive_test.exs000066400000000000000000000067141254730255300245720ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.ArchiveTest do use MixTest.Case defmodule ArchiveProject do def project do [app: :archive, version: "0.1.0", elixir: "~> 0.1.0"] end end defmodule ArchiveProject2 do def project do [app: :archive, version: "0.2.0"] end end test "archive" do File.rm_rf! tmp_path("userhome") System.put_env "MIX_ARCHIVES", tmp_path("userhome/.mix/archives/") Mix.Project.push(ArchiveProject) in_fixture "archive", fn() -> # Install it! Mix.Tasks.Archive.Build.run ["--no-elixir-version-check"] assert File.regular? "archive-0.1.0.ez" assert_received {:mix_shell, :info, ["Generated archive archive-0.1.0.ez with MIX_ENV=dev"]} send self, {:mix_shell_input, :yes?, true} Mix.Tasks.Archive.Install.run [] assert File.regular? tmp_path("userhome/.mix/archives/archive-0.1.0.ez") # Check that the version warning is printed after installation version_error = "warning: the archive archive-0.1.0 requires Elixir \"~> 0.1.0\" but you are running on v#{System.version}" assert_received {:mix_shell, :error, [^version_error]} archive = tmp_path("userhome/.mix/archives/archive-0.1.0.ez/archive-0.1.0/ebin") assert to_char_list(archive) in :code.get_path # Load it! Mix.Local.append_archives assert_received {:mix_shell, :error, [^version_error]} # List it! Mix.Tasks.Local.run [] info = "mix local.sample # A local install sample" assert_received {:mix_shell, :info, [^info]} Mix.Tasks.Archive.run [] assert_received {:mix_shell, :info, ["* archive-0.1.0.ez"]} # Run it! Mix.Task.run "local.sample" assert_received {:mix_shell, :info, ["sample"]} # Install new version! Mix.Project.push(ArchiveProject2) Mix.Tasks.Archive.Build.run ["--no_compile"] assert File.regular? "archive-0.2.0.ez" assert_received {:mix_shell, :info, ["Generated archive archive-0.2.0.ez with MIX_ENV=dev"]} send self, {:mix_shell_input, :yes?, true} Mix.Tasks.Archive.Install.run [] assert File.regular? tmp_path("userhome/.mix/archives/archive-0.2.0.ez") # Re-install an existing version send self, {:mix_shell_input, :yes?, true} Mix.Tasks.Archive.Install.run [] assert File.regular? tmp_path("userhome/.mix/archives/archive-0.2.0.ez") # Try to install a missing version assert_raise Mix.Error, fn -> send self, {:mix_shell_input, :yes?, true} Mix.Tasks.Archive.Install.run ["./archive-0.0.0.ez"] end assert File.regular? tmp_path("userhome/.mix/archives/archive-0.2.0.ez") # We don't do the assertion below on Windows because # the archive is open by Erlang code server and the archive # is not effectively removed until the Erlang process exits. unless match? {:win32, _}, :os.type do refute File.regular? tmp_path("userhome/.mix/archives/archive-0.1.0.ez") end # Load it! No warnings because there is no :elixir in mix.exs. Mix.Local.append_archives refute_received {:mix_shell, :error, [_]} # Remove it! send self, {:mix_shell_input, :yes?, true} Mix.Tasks.Archive.Uninstall.run ["archive-0.2.0.ez"] # See reason for previous refutation. unless match? {:win32, _}, :os.type do refute File.regular? tmp_path("userhome/.mix/archives/archive-0.2.0.ez") end end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/clean_test.exs000066400000000000000000000022441254730255300242250ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.CleanTest do use MixTest.Case defmodule Sample do def project do [ app: :sample, version: "0.1.0", deps: [ {:ok, "0.1.0", path: "deps/ok"}, {:unknown, "0.1.0", git: "deps/unknown"} ] ] end end setup do Mix.Project.push Sample :ok end test "cleans the application build" do in_fixture "deps_status", fn -> File.mkdir_p! "_build/dev/lib/sample" File.mkdir_p! "_build/test/lib/sample" File.mkdir_p! "_build/dev/lib/ok" Mix.Tasks.Clean.run [] refute File.exists?("_build/dev/lib/sample") refute File.exists?("_build/test/lib/sample") assert File.exists?("_build/dev/lib/ok") end end test "cleans dependencies build" do in_fixture "deps_status", fn -> File.mkdir_p! "_build/dev/lib/ok" File.mkdir_p! "_build/test/lib/ok" Mix.Tasks.Clean.run ["--deps", "--only", "dev"] refute File.exists?("_build/dev") assert File.exists?("_build/test") Mix.Tasks.Clean.run ["--deps"] refute File.exists?("_build/test") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/cmd_test.exs000066400000000000000000000011101254730255300236750ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.CmdTest do use MixTest.Case test "runs the command for each app" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project(:umbrella, ".", fn _ -> Mix.Task.run "cmd", ["echo", "hello"] nl = os_newline assert_received {:mix_shell, :info, ["==> bar"]} assert_received {:mix_shell, :run, ["hello" <> ^nl]} assert_received {:mix_shell, :info, ["==> foo"]} assert_received {:mix_shell, :run, ["hello" <> ^nl]} end) end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.app_test.exs000066400000000000000000000062111254730255300253500ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.AppTest do use MixTest.Case defmodule CustomProject do def project do [app: :custom_project, version: "0.2.0"] end def application do [maxT: :infinity, applications: [:example_app]] end end defmodule InvalidProject do def project do [app: :invalid_project, version: "0.3.0"] end def application do case Process.get(:error) do :modules -> [modules: :invalid] :maxT -> [maxT: :invalid] :registered -> [registered: ["invalid"]] :included_applications -> [included_applications: ["invalid"]] :applications -> [applications: ["invalid"]] :env -> [env: [:a]] :mod -> [mod: {Mod}] :start_phases -> [start_phases: [:invalid]] end end end defmodule InvalidVsnProject do def project do [app: :invalid_vsn_project, version: "0.3"] end end test "generates .app file when changes happen" do Mix.Project.push MixTest.Case.Sample in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.Elixir.run([]) assert Mix.Tasks.Compile.App.run([]) == :ok contents = File.read!("_build/dev/lib/sample/ebin/sample.app") assert contents =~ "{application,sample" assert contents =~ "0.1.0" assert contents =~ "'Elixir.A'" assert contents =~ "{applications,[kernel,stdlib,elixir]}" assert Mix.Tasks.Compile.App.run([]) == :noop end end test "use custom application settings" do Mix.Project.push CustomProject in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.Elixir.run([]) Mix.Tasks.Compile.App.run([]) contents = File.read!("_build/dev/lib/custom_project/ebin/custom_project.app") assert contents =~ "0.2.0" assert contents =~ "{maxT,infinity}" assert contents =~ "{applications,[kernel,stdlib,elixir,example_app]}" end end test "application properties validation" do Mix.Project.push InvalidProject in_fixture "no_mixfile", fn -> for error <- [:modules, :maxT, :registered, :included_applications, :applications, :env, :mod, :start_phases] do Process.put(:error, error) assert_raise Mix.Error, ~r/:#{error}/, fn -> Mix.Tasks.Compile.App.run([]) end end end end test ".app contains description and registered (as required by systools)" do Mix.Project.push MixTest.Case.Sample in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.Elixir.run([]) assert Mix.Tasks.Compile.App.run([]) == :ok {:ok, [{_app, _, properties}]} = :file.consult("_build/dev/lib/sample/ebin/sample.app") assert properties[:registered] == [] assert properties[:description] == 'sample' assert properties[:applications] == [:kernel, :stdlib, :elixir] assert Mix.Tasks.Compile.App.run([]) == :noop end end test "raise on invalid version" do Mix.Project.push InvalidVsnProject in_fixture "no_mixfile", fn -> assert_raise Mix.Error, "Expected :version to be a SemVer version", fn -> Mix.Tasks.Compile.App.run([]) end end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.elixir_test.exs000066400000000000000000000205751254730255300260750ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.ElixirTest do use MixTest.Case setup do Mix.Project.push MixTest.Case.Sample :ok end test "compiles a project without per environment build" do Mix.Project.pop Mix.ProjectStack.post_config [build_per_environment: false] Mix.Project.push MixTest.Case.Sample in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.Elixir.run [] assert File.regular?("_build/shared/lib/sample/ebin/Elixir.A.beam") assert File.regular?("_build/shared/lib/sample/ebin/Elixir.B.beam") assert File.regular?("_build/shared/lib/sample/ebin/Elixir.C.beam") assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/c.ex"]} end end test "compiles a project with per environment build" do in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.Elixir.run [] assert File.regular?("_build/dev/lib/sample/ebin/Elixir.A.beam") assert File.regular?("_build/dev/lib/sample/ebin/Elixir.B.beam") assert File.regular?("_build/dev/lib/sample/ebin/Elixir.C.beam") assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/c.ex"]} end end test "recompiles project if elixir version changed" do in_fixture "no_mixfile", fn -> Mix.Tasks.Compile.run [] purge [A, B, C] assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert System.version == Mix.Dep.Lock.elixir_vsn Mix.Task.clear File.write!("_build/dev/lib/sample/.compile.lock", "the_past") File.touch!("_build/dev/lib/sample/.compile.lock", {{2010, 1, 1}, {0, 0, 0}}) Mix.Tasks.Compile.run [] assert System.version == Mix.Dep.Lock.elixir_vsn assert File.stat!("_build/dev/lib/sample/.compile.lock").mtime > {{2010, 1, 1}, {0, 0, 0}} end end test "does not write beam down on failures" do import ExUnit.CaptureIO in_tmp "blank", fn -> File.mkdir_p!("lib") File.write!("lib/a.ex", "raise ~s(oops)") capture_io fn -> assert catch_exit(Mix.Tasks.Compile.Elixir.run []) == {:shutdown, 1} end refute File.regular?("_build/dev/lib/sample/ebin/Elixir.A.beam") end end test "removes, purges and deletes old artifacts" do in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.Elixir.run([]) == :ok assert File.regular?("_build/dev/lib/sample/ebin/Elixir.A.beam") assert Code.ensure_loaded?(A) File.rm!("lib/a.ex") assert Mix.Tasks.Compile.Elixir.run([]) == :ok refute File.regular?("_build/dev/lib/sample/ebin/Elixir.A.beam") refute Code.ensure_loaded?(A) refute String.contains?(File.read!("_build/dev/lib/sample/.compile.elixir"), "Elixir.A") end end test "compiles only changed files" do in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.Elixir.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} Mix.shell.flush purge [A, B, C] future = {{2020, 1, 1}, {0, 0, 0}} File.touch!("lib/a.ex", future) Mix.Tasks.Compile.Elixir.run [] assert_received {:mix_shell, :error, ["warning: mtime (modified time) for \"lib/a.ex\" was set to the future, resetting to now"]} refute_received {:mix_shell, :error, ["warning: mtime (modified time) for \"lib/b.ex\" was set to the future, resetting to now"]} assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]} File.touch!("_build/dev/lib/sample/.compile.elixir", future) assert Mix.Tasks.Compile.Elixir.run([]) == :noop end end test "compiles dependent changed modules" do in_fixture "no_mixfile", fn -> File.write!("lib/a.ex", "defmodule A, do: B.module_info") assert Mix.Tasks.Compile.Elixir.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} Mix.shell.flush purge [A, B, C] future = {{2020, 1, 1}, {0, 0, 0}} File.touch!("lib/b.ex", future) Mix.Tasks.Compile.Elixir.run [] assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} end end test "compiles dependent changed modules even on removal" do in_fixture "no_mixfile", fn -> File.write!("lib/a.ex", "defmodule A, do: B.module_info") assert Mix.Tasks.Compile.Elixir.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]} Mix.shell.flush purge [A, B, C] File.rm("lib/b.ex") File.write!("lib/a.ex", "defmodule A, do: nil") Mix.Tasks.Compile.Elixir.run [] assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]} end end test "compiles dependent changed files" do in_fixture "no_mixfile", fn -> File.touch!("lib/a.eex") File.write!("lib/a.ex", """ defmodule A do @external_resource "lib/b.eex" @external_resource "lib/a.eex" def a, do: :ok end """) assert Mix.Tasks.Compile.Elixir.run([]) == :ok Mix.shell.flush purge [A, B, C] File.touch!("lib/a.eex", {{2020, 1, 1}, {0, 0, 0}}) assert Mix.Tasks.Compile.Elixir.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]} end end test "recompiles with --force" do in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.Elixir.run([]) == :ok purge [A, B, C] # Now we have a noop assert Mix.Tasks.Compile.Elixir.run([]) == :noop # --force assert Mix.Tasks.Compile.Elixir.run(["--force"]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} end end defmodule SourcePathsProject do def project do [app: :source_paths, elixirc_paths: ["web", "lib", "lib/foo"]] end end test "use custom source paths" do Mix.Project.push SourcePathsProject in_fixture "no_mixfile", fn -> File.mkdir_p! "web" File.write! "web/ab.ex", """ defmodule AB, do: :ok """ # Nothing to compile with the custom source paths assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "web"]) assert_received {:mix_shell, :info, ["Compiled web/ab.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"]) assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled web/ab.ex"]} # Compiling just web does not remove lib artifacts assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "web"]) refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"]) refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} end end test "use custom source paths in subdirs" do Mix.Project.push SourcePathsProject in_fixture "no_mixfile", fn -> File.mkdir_p! "lib/foo" File.write! "lib/foo/ab.ex", """ defmodule AB, do: :ok """ # Nested file (and nested file only) is compiled just once assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib/foo"]) assert_received {:mix_shell, :info, ["Compiled lib/foo/ab.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/foo/ab.ex"]} assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"]) assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} refute_received {:mix_shell, :info, ["Compiled lib/foo/ab.ex"]} # Compiling just lib/foo does not remove lib artifacts assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib/foo"]) refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"]) refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]} end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.erlang_test.exs000066400000000000000000000036121254730255300260420ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.ErlangTest do use MixTest.Case import ExUnit.CaptureIO setup do Mix.Project.push MixTest.Case.Sample :ok end test "compilation continues if one file fails to compile" do in_fixture "compile_erlang", fn -> File.write! "src/zzz.erl", """ -module(zzz). def zzz(), do: b """ assert_raise Mix.Error, fn -> capture_io fn -> Mix.Tasks.Compile.Erlang.run [] end end assert File.regular?("_build/dev/lib/sample/ebin/b.beam") assert File.regular?("_build/dev/lib/sample/ebin/c.beam") end end test "compiles src/b.erl and src/c.erl" do in_fixture "compile_erlang", fn -> assert Mix.Tasks.Compile.Erlang.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled src/b.erl"]} assert_received {:mix_shell, :info, ["Compiled src/c.erl"]} assert File.regular?("_build/dev/lib/sample/ebin/b.beam") assert File.regular?("_build/dev/lib/sample/ebin/c.beam") assert File.read!("_build/dev/lib/sample/.compile.erlang") == "_build/dev/lib/sample/ebin/b.beam\n" <> "_build/dev/lib/sample/ebin/c.beam" assert Mix.Tasks.Compile.Erlang.run([]) == :noop refute_received {:mix_shell, :info, ["Compiled src/b.erl"]} assert Mix.Tasks.Compile.Erlang.run(["--force"]) == :ok assert_received {:mix_shell, :info, ["Compiled src/b.erl"]} assert_received {:mix_shell, :info, ["Compiled src/c.erl"]} end end test "removes old artifact files" do in_fixture "compile_erlang", fn -> assert Mix.Tasks.Compile.Erlang.run([]) == :ok assert File.regular?("_build/dev/lib/sample/ebin/b.beam") File.rm!("src/b.erl") assert Mix.Tasks.Compile.Erlang.run([]) == :ok refute File.regular?("_build/dev/lib/sample/ebin/b.beam") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.leex_test.exs000066400000000000000000000025701254730255300255310ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.LeexTest do use MixTest.Case import ExUnit.CaptureIO setup do Mix.Project.push MixTest.Case.Sample :ok end test "compilation continues if one file fails to compile" do in_fixture "compile_leex", fn -> File.write! "src/zzz.xrl", """ oops. """ assert_raise Mix.Error, fn -> capture_io fn -> Mix.Tasks.Compile.Leex.run ["--force"] end end assert File.regular?("src/test_ok.erl") end end test "compiles src/test_ok.xrl" do in_fixture "compile_leex", fn -> assert Mix.Tasks.Compile.Leex.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} assert File.regular?("src/test_ok.erl") assert Mix.Tasks.Compile.Leex.run([]) == :noop refute_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} assert Mix.Tasks.Compile.Leex.run(["--force"]) == :ok assert_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} end end test "removes old artifact files" do in_fixture "compile_leex", fn -> assert Mix.Tasks.Compile.Leex.run([]) == :ok assert File.regular?("src/test_ok.erl") File.rm!("src/test_ok.xrl") assert Mix.Tasks.Compile.Leex.run([]) == :ok refute File.regular?("src/test_ok.erl") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.protocols_test.exs000066400000000000000000000011541254730255300266150ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.ProtocolsTest do use MixTest.Case test "compiles and consolidates protocols" do Mix.Project.push MixTest.Case.Sample in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.Protocols.run([]) == :ok assert_received {:mix_shell, :info, ["Consolidated Enumerable"]} assert File.regular? "_build/dev/consolidated/Elixir.Enumerable.beam" purge [Enumerable] Code.prepend_path("_build/dev/consolidated") assert Protocol.consolidated?(Enumerable) end after purge [Enumerable] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile.yecc_test.exs000066400000000000000000000025701254730255300255170ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.Compile.YeccTest do use MixTest.Case import ExUnit.CaptureIO setup do Mix.Project.push MixTest.Case.Sample :ok end test "compilation continues if one file fails to compile" do in_fixture "compile_yecc", fn -> File.write! "src/zzz.yrl", """ oops. """ assert_raise Mix.Error, fn -> capture_io fn -> Mix.Tasks.Compile.Yecc.run ["--force"] end end assert File.regular?("src/test_ok.erl") end end test "compiles src/test_ok.yrl" do in_fixture "compile_yecc", fn -> assert Mix.Tasks.Compile.Yecc.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled src/test_ok.yrl"]} assert File.regular?("src/test_ok.erl") assert Mix.Tasks.Compile.Yecc.run([]) == :noop refute_received {:mix_shell, :info, ["Compiled src/test_ok.yrl"]} assert Mix.Tasks.Compile.Yecc.run(["--force"]) == :ok assert_received {:mix_shell, :info, ["Compiled src/test_ok.yrl"]} end end test "removes old artifact files" do in_fixture "compile_yecc", fn -> assert Mix.Tasks.Compile.Yecc.run([]) == :ok assert File.regular?("src/test_ok.erl") File.rm!("src/test_ok.yrl") assert Mix.Tasks.Compile.Yecc.run([]) == :ok refute File.regular?("src/test_ok.erl") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/compile_test.exs000066400000000000000000000053351254730255300245770ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.CompileTest do use MixTest.Case defmodule CustomCompilers do def project do [compilers: [:elixir, :app, :custom]] end end defmodule Consolidation do def project do [app: :consolidation, version: "0.1.0", consolidate_protocols: true] end end setup do Mix.Project.push MixTest.Case.Sample :ok end test "compile --list with mixfile" do Mix.Tasks.Compile.run ["--list"] assert_received {:mix_shell, :info, ["\nEnabled compilers: yecc, leex, erlang, elixir, app"]} assert_received {:mix_shell, :info, ["mix compile.elixir # " <> _]} end test "compile --list with custom mixfile" do Mix.Project.push CustomCompilers Mix.Tasks.Compile.run ["--list"] assert_received {:mix_shell, :info, ["\nEnabled compilers: elixir, app, custom"]} end test "compile --list with consolidation" do Mix.Project.push Consolidation Mix.Tasks.Compile.run ["--list"] assert_received {:mix_shell, :info, ["\nEnabled compilers: yecc, leex, erlang, elixir, app, protocols"]} end test "compile a project with mixfile" do in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.run([]) == :ok assert File.regular?("_build/dev/lib/sample/ebin/Elixir.A.beam") assert File.regular?("_build/dev/lib/sample/ebin/sample.app") assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Generated sample app"]} end end test "compile a project with protocol consolidation" do Mix.Project.push Consolidation in_fixture "no_mixfile", fn -> assert Mix.Tasks.Compile.run([]) == :ok assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert_received {:mix_shell, :info, ["Consolidated Enumerable"]} assert File.regular? "_build/dev/consolidated/Elixir.Enumerable.beam" assert Mix.Tasks.Compile.run([]) == :noop refute_received {:mix_shell, :info, ["Consolidated Enumerable"]} assert Mix.Tasks.App.Start.run([]) == :ok assert Protocol.consolidated?(Enumerable) end after purge [Enumerable] end test "compile a project with multiple compilers and a syntax error in an erlang file" do in_fixture "no_mixfile", fn -> import ExUnit.CaptureIO File.mkdir! "src" File.write! "src/a.erl", """ -module(b). def b(), do: b """ assert File.regular?("src/a.erl") assert_raise Mix.Error, fn -> capture_io fn -> Mix.Tasks.Compile.run ["--force"] end end refute File.regular?("ebin/Elixir.A.beam") refute File.regular?("ebin/Elixir.B.beam") refute File.regular?("ebin/Elixir.C.beam") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/deps.git_test.exs000066400000000000000000000245601254730255300246650ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.DepsGitTest do use MixTest.Case defmodule DepsOnGitApp do def project do [ app: :deps_on_git_app, version: "0.1.0", deps: [ {:deps_on_git_repo, "0.2.0", git: MixTest.Case.fixture_path("deps_on_git_repo")} ] ] end end defmodule GitApp do def project do [ app: :git_app, version: "0.1.0", deps: [ {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end defmodule GitSubmodulesApp do def project do [ app: :git_app, version: "0.1.0", deps: [ {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), submodules: true} ] ] end end defmodule GitErrorApp do def project do [ deps: [ {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("not_git_repo")} ] ] end end test "gets and updates git repos with compilation" do Mix.Project.push GitApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} assert File.read!("mix.lock") =~ ~r/"git_repo": {:git, #{inspect fixture_path("git_repo")}, "[a-f0-9]+", \[\]}/ Mix.Tasks.Deps.Update.run ["--all"] message = "* Updating git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} end end test "gets and updates git repos with submodules" do Mix.Project.push GitSubmodulesApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} assert File.read!("mix.lock") =~ "submodules: true" end end test "handles invalid .git directory" do Mix.Project.push GitApp in_fixture "no_mixfile", fn -> File.mkdir_p!("deps/git_repo/.git") Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} end end test "handles missing .git directory" do Mix.Project.push GitApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} File.rm_rf!("deps/git_repo/.git") assert_raise Mix.Error, "Can't continue due to errors on dependencies", fn -> Mix.Tasks.Deps.Check.run ["git_repo"] end end end test "gets and updates many levels deep dependencies" do Mix.Project.push DepsOnGitApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} message = "* Getting deps_on_git_repo (#{fixture_path("deps_on_git_repo")})" assert_received {:mix_shell, :info, [^message]} assert File.exists?("deps/deps_on_git_repo/mix.exs") assert File.rm("deps/deps_on_git_repo/.fetch") == :ok assert File.exists?("deps/git_repo/mix.exs") assert File.rm("deps/git_repo/.fetch") == :ok # Compile the dependencies Mix.Tasks.Deps.Compile.run [] # Now update children and make sure it propagates Mix.Tasks.Deps.Update.run ["git_repo"] assert File.exists?("deps/deps_on_git_repo/.fetch") assert File.exists?("deps/git_repo/.fetch") # Compile git repo but unload it so... Mix.Tasks.Deps.Compile.run ["git_repo"] assert File.exists?("_build/dev/lib/git_repo/ebin") Code.delete_path("_build/dev/lib/git_repo/ebin") # Deps on git repo loads it automatically on compile Mix.Task.reenable "deps.loadpaths" Mix.Tasks.Deps.Compile.run ["deps_on_git_repo"] assert File.exists?("_build/dev/lib/deps_on_git_repo/ebin") end after purge [GitRepo, GitRepo.Mix] end test "recompiles the project when a dep is fetched" do Mix.Project.push GitApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] assert File.exists?("deps/git_repo/.fetch") # We can compile just fine Mix.Tasks.Compile.run [] assert_received {:mix_shell, :info, ["Compiled lib/git_repo.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} # Clear up to prepare for the update File.rm("_build/dev/lib/git_repo/ebin/Elixir.GitRepo.beam") File.rm("_build/dev/lib/git_repo/.compile.elixir") File.rm("deps/git_repo/.fetch") Mix.Task.clear Mix.shell.flush purge [A, B, C, GitRepo] # Update will mark the update required Mix.Tasks.Deps.Update.run ["git_repo"] assert File.exists?("deps/git_repo/.fetch") ensure_touched("deps/git_repo/.fetch") # Ensure timestamp differs # mix deps.compile is required... Mix.Tasks.Deps.run [] msg = " the dependency build is outdated, please run `mix deps.compile`" assert_received {:mix_shell, :info, [^msg]} # But also ran automatically Mix.Tasks.Compile.run [] assert_received {:mix_shell, :info, ["Compiled lib/git_repo.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]} assert File.exists?("_build/dev/lib/git_repo/.compile.fetch") :ok end after purge [A, B, C, GitRepo, GitRepo.Mix] end test "all up to date dependencies" do Mix.Project.push GitApp in_fixture "no_mixfile", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} Mix.Tasks.Deps.Get.run [] assert_received {:mix_shell, :info, ["All dependencies up to date"]} end after purge [GitRepo, GitRepo.Mix] end test "updates the lock when the repo updates" do Mix.Project.push GitApp # Get git repo first revision [last, first|_] = get_git_repo_revs in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), first, []}} Mix.Tasks.Deps.Get.run [] refute File.exists?("deps/git_repo/lib/git_repo.ex") assert File.read!("mix.lock") =~ first Mix.Tasks.Deps.Update.run ["git_repo"] assert File.exists?("deps/git_repo/lib/git_repo.ex") assert File.read!("mix.lock") =~ last Mix.Tasks.Deps.Clean.run ["--all"] refute File.exists?("deps/git_repo/lib/git_repo.ex") assert File.read!("mix.lock") =~ last Mix.Tasks.Deps.Clean.run ["--unlock", "--all"] refute File.read!("mix.lock") =~ last end after purge [GitRepo, GitRepo.Mix] end test "updates the repo when the lock updates" do Mix.Project.push GitApp [last, first|_] = get_git_repo_revs in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), first, []}} Mix.Tasks.Deps.Get.run [] refute File.exists?("deps/git_repo/lib/git_repo.ex") assert File.read!("mix.lock") =~ first # Update the lock and now we should get an error Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), last, []}} assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Check.run [] end # Flush the errors we got, move to a clean slate Mix.shell.flush Mix.Task.clear # Calling get should update the dependency Mix.Tasks.Deps.Get.run [] assert File.exists?("deps/git_repo/lib/git_repo.ex") assert File.read!("mix.lock") =~ last message = "* Updating git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} # Check we got no error refute_received {:mix_shell, :error, _} end after purge [GitRepo, GitRepo.Mix] end test "updates the repo and the lock when the mixfile updates" do Mix.Project.push GitApp [last, first|_] = get_git_repo_revs in_fixture "no_mixfile", fn -> # Move to the first version Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), first, []}} Mix.Tasks.Deps.Get.run [] assert File.read!("mix.lock") =~ first # Update the project configuration. It should force an update. refresh deps: [{:git_repo, "0.1.0", git: fixture_path("git_repo"), ref: last}] Mix.Tasks.Deps.run [] msg = " lock outdated: the lock is outdated compared to the options in your mixfile" assert_received {:mix_shell, :info, [^msg]} # Check an update was triggered Mix.Tasks.Deps.Get.run [] assert File.read!("mix.lock") =~ last message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} # Check we got no error refute_received {:mix_shell, :error, _} end after purge [GitRepo, GitRepo.Mix] end test "does not attempt to compile projects that could not be retrieved" do Mix.Project.push GitErrorApp in_fixture "no_mixfile", fn -> exception = assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Get.run [] end assert Exception.message(exception) =~ "Command `git clone" end end test "does not load bad mixfiles on get" do Mix.Project.push GitApp [last, _, bad|_] = get_git_repo_revs in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), bad, []}} catch_error(Mix.Tasks.Deps.Get.run []) Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), last, []}} Mix.Tasks.Deps.Get.run [] assert File.read!("mix.lock") =~ last end after purge [GitRepo, GitRepo.Mix] end test "does not load bad mixfiles on update" do Mix.Project.push GitApp [last, _, bad|_] = get_git_repo_revs in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: {:git, fixture_path("git_repo"), bad, []}} catch_error(Mix.Tasks.Deps.Get.run []) Mix.Tasks.Deps.Update.run ["git_repo"] Mix.Tasks.Deps.Compile.run ["git_repo"] assert File.read!("mix.lock") =~ last end after purge [GitRepo, GitRepo.Mix] end defp refresh(post_config) do %{name: name, file: file} = Mix.Project.pop Mix.ProjectStack.post_config(post_config) Mix.Project.push(name, file) end defp get_git_repo_revs do File.cd! fixture_path("git_repo"), fn -> Regex.split ~r(\r?\n), System.cmd("git", ["log", "--format=%H"]) |> elem(0) end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/deps.path_test.exs000066400000000000000000000016151254730255300250320ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.DepsPathTest do use MixTest.Case defmodule DepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:raw_repo, "0.1.0", path: "custom/raw_repo"} ] ] end end test "does not mark for compilation on get/update" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run ["--all"] refute File.exists?("custom/raw_repo/.fetch") end end test "compiles ands runs even if lock does not match" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> Mix.Dep.Lock.write %{raw_repo: "abcdef"} Mix.Tasks.Run.run ["-e", "Mix.shell.info RawRepo.hello"] assert_received {:mix_shell, :info, ["==> raw_repo"]} assert_received {:mix_shell, :info, ["world"]} end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/deps_test.exs000066400000000000000000000431261254730255300241020ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.DepsTest do use MixTest.Case defmodule DepsApp do def project do [ app: :deps, version: "0.1.0", deps: [ {:ok, "0.1.0", github: "elixir-lang/ok"}, {:invalidvsn, "0.2.0", path: "deps/invalidvsn"}, {:invalidapp, "0.1.0", path: "deps/invalidapp"}, {:noappfile, "0.1.0", path: "deps/noappfile"}, ] ] end end defmodule SuccessfulDepsApp do def project do [ app: :sample, version: "0.1.0", deps: [ {:ok, "0.1.0", path: "deps/ok"} ] ] end end defmodule ReqDepsApp do def project do [ app: :req_deps, version: "0.1.0", deps: [ {:ok, ">= 2.0.0", path: "deps/ok"}, {:noappfile, path: "deps/noappfile", app: false}, {:apppath, path: "deps/noappfile", app: "../deps/ok/ebin/ok.app"} ] ] end end test "prints list of dependencies and their status" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, ["* ok (https://github.com/elixir-lang/ok.git)"]} assert_received {:mix_shell, :info, [" the dependency is not available, run `mix deps.get`"]} assert_received {:mix_shell, :info, ["* invalidvsn (deps/invalidvsn)"]} assert_received {:mix_shell, :info, [" the app file contains an invalid version: :ok"]} assert_received {:mix_shell, :info, ["* invalidapp (deps/invalidapp)"]} assert_received {:mix_shell, :info, [" the app file at _build/dev/lib/invalidapp/ebin/invalidapp.app is invalid"]} assert_received {:mix_shell, :info, ["* noappfile (deps/noappfile)"]} assert_received {:mix_shell, :info, [" could not find an app file at _build/dev/lib/noappfile/ebin/noappfile.app" <> _]} end end test "prints list of dependencies and their status, including req mismatches and custom apps" do Mix.Project.push ReqDepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, ["* ok (deps/ok)"]} assert_received {:mix_shell, :info, [" the dependency does not match the requirement \">= 2.0.0\", got \"0.1.0\""]} assert_received {:mix_shell, :info, ["* noappfile (deps/noappfile)"]} assert_received {:mix_shell, :info, ["* apppath (deps/noappfile)"]} refute_received {:mix_shell, :info, [" could not find app file at _build/dev/lib/noappfile/ebin/apppath.app" <> _]} refute_received {:mix_shell, :info, [" could not find app file at _build/dev/lib/noappfile/ebin/noappfile.app" <> _]} end end test "prints elixir req mismatches" do Mix.Project.push ReqDepsApp in_fixture "deps_status", fn -> File.write! "deps/ok/mix.exs", """ defmodule Deps.OkApp do use Mix.Project def project do [elixir: "~> 0.1.0", app: :ok, version: "2.0.0"] end end """ Mix.Tasks.Deps.Compile.run [:ok] msg = "warning: the dependency ok requires Elixir \"~> 0.1.0\" " <> "but you are running on v#{System.version}" assert_received {:mix_shell, :error, [^msg]} Mix.Tasks.Deps.Compile.run [] end end test "prints list of dependencies and their lock status" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> File.cd!("deps/ok", fn -> System.cmd("git", ["init"]) end) Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, ["* ok (https://github.com/elixir-lang/ok.git)"]} assert_received {:mix_shell, :info, [" the dependency is not locked"]} Mix.Dep.Lock.write %{ok: {:git, "git://github.com/elixir-lang/ok.git", "abcdefghi", []}} Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, ["* ok (https://github.com/elixir-lang/ok.git)"]} assert_received {:mix_shell, :info, [" locked at abcdefg"]} assert_received {:mix_shell, :info, [" lock mismatch: the dependency is out of date (run `mix deps.get` to fetch locked version)"]} Mix.Dep.Lock.write %{ok: {:git, "git://github.com/elixir-lang/another.git", "abcdefghi", []}} Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, ["* ok (https://github.com/elixir-lang/ok.git)"]} assert_received {:mix_shell, :info, [" lock outdated: the lock is outdated compared to the options in your mixfile"]} end end test "checks list of dependencies and their status with success" do Mix.Project.push SuccessfulDepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Check.run [] end end test "checks list of dependencies and their status on failure" do Mix.Project.push DepsApp in_fixture "deps_status", fn -> assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Check.run [] end assert_received {:mix_shell, :error, ["* ok (https://github.com/elixir-lang/ok.git)"]} assert_received {:mix_shell, :error, [" the dependency is not available, run `mix deps.get`"]} assert_received {:mix_shell, :error, ["* invalidvsn (deps/invalidvsn)"]} assert_received {:mix_shell, :error, [" the app file contains an invalid version: :ok"]} assert_received {:mix_shell, :error, ["* invalidapp (deps/invalidapp)"]} assert_received {:mix_shell, :error, [" the app file at _build/dev/lib/invalidapp/ebin/invalidapp.app is invalid"]} # This one is compiled automatically refute_received {:mix_shell, :error, ["* noappfile (deps/noappfile)"]} refute_received {:mix_shell, :error, [" could not find an app file at _build/dev/lib/noappfile/ebin/noappfile.app" <> _]} end end test "compiles and prunes builds per environment" do Mix.Project.push SuccessfulDepsApp in_fixture "deps_status", fn -> # Start from scratch! File.rm_rf("_build") Mix.Tasks.Deps.Compile.run [] Mix.Tasks.Deps.Check.run [] assert File.exists?("_build/dev/lib/ok/ebin/ok.app") assert File.exists?("_build/dev/lib/ok/priv/sample") Mix.Tasks.Compile.run [] assert File.exists?("_build/dev/lib/sample/ebin/sample.app") Mix.ProjectStack.post_config [deps: []] Mix.Project.pop Mix.Project.push SuccessfulDepsApp Mix.Tasks.Deps.Check.run [] refute File.exists?("_build/dev/lib/ok/ebin/ok.app") assert File.exists?("_build/dev/lib/sample/ebin/sample.app") end end test "unlocks all deps" do Mix.Project.push DepsApp in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: "abcdef"} assert Mix.Dep.Lock.read == %{git_repo: "abcdef"} Mix.Tasks.Deps.Unlock.run ["--all"] assert Mix.Dep.Lock.read == %{} end end test "unlocks unused deps" do Mix.Project.push DepsApp in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{whatever: "abcdef", ok: "abcdef"} assert Mix.Dep.Lock.read == %{whatever: "abcdef", ok: "abcdef"} Mix.Tasks.Deps.Unlock.run ["--unused"] assert Mix.Dep.Lock.read == %{ok: "abcdef"} end end test "unlocks specific deps" do Mix.Project.push DepsApp in_fixture "no_mixfile", fn -> Mix.Dep.Lock.write %{git_repo: "abcdef", another: "hash"} Mix.Tasks.Deps.Unlock.run ["git_repo", "unknown"] assert Mix.Dep.Lock.read == %{another: "hash"} error = "warning: unknown dependency is not locked" assert_received {:mix_shell, :error, [^error]} end end ## Deps environment defmodule DepsEnvApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:raw_repo, "0.1.0", path: "custom/raw_repo"} ] ] end end defmodule CustomDepsEnvApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:raw_repo, "0.1.0", path: "custom/raw_repo", env: :dev} ] ] end end test "sets deps env to prod by default" do Mix.Project.push DepsEnvApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Update.run ["--all"] assert_received {:mix_shell, :info, [":raw_repo env is prod"]} end end test "can customize environment" do Mix.Project.push CustomDepsEnvApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Update.run ["--all"] assert_received {:mix_shell, :info, [":raw_repo env is dev"]} end end ## Nested dependencies defmodule DivergedDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:deps_repo, "0.1.0", path: "custom/deps_repo"}, {:bad_deps_repo, "0.1.0", path: "custom/bad_deps_repo"} ] ] end end defmodule ConvergedDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:deps_repo, "0.1.0", path: "custom/deps_repo"}, {:git_repo, ">= 0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end defmodule OverridenDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:bad_deps_repo, "0.1.0", path: "custom/bad_deps_repo"}, {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), override: true} ] ] end end defmodule NonOverridenDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:bad_deps_repo, "0.1.0", path: "custom/bad_deps_repo"}, {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end test "fails on missing dependencies" do Mix.Project.push SuccessfulDepsApp in_fixture "deps_status", fn -> assert_raise Mix.Error, ~r/Unknown dependency invalid for environment dev/, fn -> Mix.Tasks.Deps.Update.run ["invalid"] end end end test "fails on diverged dependencies" do Mix.Project.push DivergedDepsApp in_fixture "deps_status", fn -> assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Check.run [] end receive do {:mix_shell, :error, [" different specs were given for the git_repo app:" <> _ = msg]} -> assert msg =~ "In custom/deps_repo/mix.exs:" assert msg =~ "{:git_repo, \"0.1.0\", [git: #{inspect fixture_path("git_repo")}]}" after 0 -> flunk "expected diverged error message" end end end test "fails on diverged dependencies by requirement" do Mix.Project.push ConvergedDepsApp in_fixture "deps_status", fn -> File.write! "custom/deps_repo/mix.exs", """ defmodule DepsRepo do use Mix.Project def project do [ app: :deps_repo, version: "0.1.0", deps: [ {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end """ assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Get.run [] Mix.Tasks.Deps.Check.run [] end receive do {:mix_shell, :error, [" the dependency git_repo defined" <> _ = msg]} -> assert msg =~ "In custom/deps_repo/mix.exs:" assert msg =~ "{:git_repo, \"0.2.0\", [git: #{inspect fixture_path("git_repo")}]}" after 0 -> flunk "expected diverged req error message" end end end test "fails on diverged dependencies even when optional" do Mix.Project.push ConvergedDepsApp in_fixture "deps_status", fn -> File.write! "custom/deps_repo/mix.exs", """ defmodule DepsRepo do use Mix.Project def project do [ app: :deps_repo, version: "0.1.0", deps: [ {:git_repo, git: MixTest.Case.fixture_path("bad_git_repo"), branch: "omg"} ] ] end end """ assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Get.run [] Mix.Tasks.Deps.Check.run [] end assert_received {:mix_shell, :error, [" the dependency git_repo in mix.exs is overriding" <> _]} end end test "works with converged dependencies" do Mix.Project.push ConvergedDepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} # Make sure retriever uses converger, # so the message appears just once refute_received {:mix_shell, :info, [^message]} Mix.Task.clear Mix.Tasks.Deps.Update.run ["--all"] message = "* Updating git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} end after purge [GitRepo, GitRepo.Mix] end test "works with overridden dependencies" do Mix.Project.push OverridenDepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Get.run [] message = "* Getting git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} # Make sure retriever uses converger, # so the message appears just once refute_received {:mix_shell, :info, [^message]} Mix.Task.clear Mix.Tasks.Deps.Update.run ["--all"] message = "* Updating git_repo (#{fixture_path("git_repo")})" assert_received {:mix_shell, :info, [^message]} end after purge [GitRepo, GitRepo.Mix] end test "converged dependencies errors if not overriding" do Mix.Project.push NonOverridenDepsApp in_fixture "deps_status", fn -> assert_raise Mix.Error, fn -> Mix.Tasks.Deps.Check.run [] end receive do {:mix_shell, :error, [" the dependency git_repo in mix.exs" <> _ = msg]} -> assert msg =~ "In mix.exs:" assert msg =~ "{:git_repo, \"0.1.0\", [git: #{inspect fixture_path("git_repo")}]}" after 0 -> flunk "expected overriding error message" end end after purge [GitRepo, GitRepo.Mix] end test "checks if dependencies are using old elixir version" do Mix.Project.push SuccessfulDepsApp in_fixture "deps_status", fn -> Mix.Tasks.Deps.Compile.run [] Mix.Tasks.Deps.Check.run [] File.mkdir_p!("_build/dev/lib/ok/ebin") File.write!("_build/dev/lib/ok/.compile.lock", "the_future") Mix.Task.clear msg = " the dependency is built with an out-of-date elixir version, run `mix deps.compile`" Mix.Tasks.Deps.run [] assert_received {:mix_shell, :info, [^msg]} # deps.check will automatically recompile it Mix.Tasks.Deps.Check.run [] Mix.Tasks.Deps.run [] refute_received {:mix_shell, :info, [^msg]} end end defmodule NonCompilingDeps do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:deps_repo, "0.1.0", path: "custom/deps_repo", compile: false}, {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), compile: false} ] ] end end test "does not compile deps that have explicit flag" do Mix.Project.push NonCompilingDeps in_fixture "deps_status", fn -> Mix.Tasks.Deps.Compile.run [] refute_received {:mix_shell, :info, ["==> deps_repo"]} refute_received {:mix_shell, :info, ["==> git_repo"]} end end defmodule DupDeps do def project do [ app: :raw_sample, version: "0.1.0", deps: [ # Simulate dependencies gathered together from umbrella {:ok, "0.1.0", path: "deps/ok"}, {:ok, "0.1.0", path: "deps/ok"} ] ] end end test "converges duplicated deps at the same level" do Mix.Project.push DupDeps in_fixture "deps_status", fn -> Mix.Tasks.Deps.run [] msg = "* ok 0.1.0 (deps/ok)" assert_received {:mix_shell, :info, [^msg]} refute_received {:mix_shell, :info, [^msg]} end end defmodule CleanDepsApp do def project do [ app: :raw_sample, version: "0.1.0", deps: [ {:git_repo, ">= 0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end test "cleans dependencies" do Mix.Project.push CleanDepsApp in_fixture "deps_status", fn -> File.mkdir_p!("_build/dev/lib/raw_sample") File.mkdir_p!("_build/dev/lib/git_repo") File.mkdir_p!("_build/test/lib/git_repo") message = "mix deps.clean expects dependencies as arguments or " <> "a flag indicating which dependencies to clean. " <> "The --all option will clean all dependencies while " <> "the --unused option cleans unused dependencies." assert_raise Mix.Error, message, fn -> Mix.Tasks.Deps.Clean.run [] end Mix.Tasks.Deps.Clean.run ["--only", "dev", "--all"] refute File.exists?("_build/dev/lib/git_repo") assert File.exists?("_build/test/lib/git_repo") assert File.exists?("_build/dev/lib/raw_sample") Mix.Tasks.Deps.Clean.run ["--all"] refute File.exists?("_build/dev/lib/git_repo") refute File.exists?("_build/test/lib/git_repo") assert File.exists?("_build/dev/lib/raw_sample") end end test "cleans unused dependencies" do Mix.Project.push CleanDepsApp in_fixture "deps_status", fn -> File.mkdir_p!("_build/dev/lib/raw_sample") File.mkdir_p!("deps/git_repo") File.mkdir_p!("_build/dev/lib/git_repo") File.mkdir_p!("deps/git_repo_unused") File.mkdir_p!("_build/dev/lib/git_repo_unused") Mix.Tasks.Deps.Clean.run ["--unused"] assert File.exists?("deps/git_repo") assert File.exists?("_build/dev/lib/git_repo") refute File.exists?("deps/git_repo_unused") refute File.exists?("_build/dev/lib/git_repo_unused") assert File.exists?("_build/dev/lib/raw_sample") end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/do_test.exs000066400000000000000000000005561254730255300235510ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.DoTest do use MixTest.Case test "runs given tasks" do in_fixture "no_mixfile", fn -> Mix.Tasks.Do.run ["compile", "--list,", "help"] assert_received {:mix_shell, :info, ["mix help" <> _]} assert_received {:mix_shell, :info, ["mix compile.app" <> _]} end end endelixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/escript_test.exs000066400000000000000000000073541254730255300246230ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.EscriptTest do use MixTest.Case defmodule Escript do def project do [ app: :escripttest, version: "0.0.1", escript: [ main_module: Escripttest, name: "escriptest", embed_elixir: true ] ] end end defmodule EscriptWithPath do def project do [ app: :escripttestwithpath, version: "0.0.1", escript: [ app: nil, embed_elixir: true, main_module: Escripttest, path: Path.join("ebin", "escripttestwithpath") ] ] end end defmodule EscriptWithDeps do def project do [ app: :escripttestwithdeps, version: "0.0.1", escript: [main_module: Escripttest], deps: [{:ok, path: fixture_path("deps_status/deps/ok")}] ] end end defmodule EscriptErlangWithDeps do def project do [ app: :escripttesterlangwithdeps, version: "0.0.1", language: :erlang, escript: [main_module: :escripttest], deps: [{:ok, path: fixture_path("deps_status/deps/ok")}] ] end end defmodule EscriptConsolidated do def project do [ app: :escripttestconsolidated, build_embedded: true, version: "0.0.1", escript: [main_module: Escripttest] ] end end test "generate escript" do Mix.Project.push Escript in_fixture "escripttest", fn -> Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript escriptest with MIX_ENV=dev"]} assert System.cmd("escript", ["escriptest"]) == {"TEST\n", 0} Mix.Tasks.Escript.Build.run [] refute_received {:mix_shell, :info, ["Generated escript escriptest with MIX_ENV=dev"]} end end test "generate escript with config" do Mix.Project.push Escript in_fixture "escripttest", fn -> File.mkdir_p! "config" File.write! "config/config.exs", """ [foobar: [value: "FROM CONFIG", other: %{}]] """ Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript escriptest with MIX_ENV=dev"]} assert System.cmd("escript", ["escriptest"]) == {"FROM CONFIG\n", 0} end end test "generate escript with path" do Mix.Project.push EscriptWithPath in_fixture "escripttest", fn -> Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript ebin/escripttestwithpath with MIX_ENV=dev"]} assert System.cmd("escript", ["ebin/escripttestwithpath"]) == {"TEST\n", 0} end end test "generate escript with deps" do Mix.Project.push EscriptWithDeps in_fixture "escripttest", fn -> Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript escripttestwithdeps with MIX_ENV=dev"]} assert System.cmd("escript", ["escripttestwithdeps"]) == {"TEST\n", 0} end after purge [Ok.Mixfile] end test "generate escript with erlang and deps" do Mix.Project.push EscriptErlangWithDeps in_fixture "escripttest", fn -> Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript escripttesterlangwithdeps with MIX_ENV=dev"]} assert System.cmd("escript", ["escripttesterlangwithdeps"]) == {"Erlang value", 0} end after purge [Ok.Mixfile] end test "generate escript with consolidated protocols" do Mix.Project.push EscriptConsolidated in_fixture "escripttest_protocols", fn -> Mix.Tasks.Escript.Build.run [] assert_received {:mix_shell, :info, ["Generated escript escripttestconsolidated with MIX_ENV=dev"]} assert System.cmd("escript", ["escripttestconsolidated", "Enumerable"]) == {"true\n", 0} end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/help_test.exs000066400000000000000000000044471254730255300241020ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.HelpTest do use MixTest.Case import ExUnit.CaptureIO test "help lists all tasks" do in_fixture "no_mixfile", fn -> Mix.Tasks.Help.run [] assert_received {:mix_shell, :info, ["mix" <> _]} assert_received {:mix_shell, :info, ["mix help" <> _]} assert_received {:mix_shell, :info, ["mix compile" <> _]} end end test "help list default task" do in_fixture "no_mixfile", fn -> Mix.Tasks.Help.run [] {_, _, [output]} = assert_received {:mix_shell, :info, [_]} assert output =~ ~r/^mix\s+# Run the default task \(current: mix run\)/m end end defmodule Aliases do def project do [aliases: [h: "hello", c: "compile"]] end end test "help --names" do Mix.Project.push Aliases in_fixture "no_mixfile", fn -> Mix.Tasks.Help.run ["--names"] assert_received {:mix_shell, :info, ["c"]} assert_received {:mix_shell, :info, ["compile"]} assert_received {:mix_shell, :info, ["h"]} assert_received {:mix_shell, :info, ["help"]} assert_received {:mix_shell, :info, ["escript.build"]} end end test "help TASK" do in_fixture "no_mixfile", fn -> output = capture_io fn -> Mix.Tasks.Help.run ["compile"] end assert output =~ "# mix compile" assert output =~ "## Command line options" assert output =~ ~r/^Location:/m end end test "help --search PATTERN" do in_fixture "no_mixfile", fn -> Mix.Tasks.Help.run ["--search", "deps"] assert_received {:mix_shell, :info, ["mix deps" <> _]} assert_received {:mix_shell, :info, ["mix deps.clean" <> _]} end end test "help --search without pattern" do assert_raise Mix.Error, "Unexpected arguments, expected `mix help --search PATTERN`", fn -> Mix.Tasks.Help.run ["--search"] end end test "help --search without results" do in_fixture "no_mixfile", fn -> output = capture_io fn -> Mix.Tasks.Help.run ["--search", "foo"] end assert output == "" end end test "bad arguments" do assert_raise Mix.Error, "Unexpected arguments, expected `mix help` or `mix help TASK`", fn -> Mix.Tasks.Help.run ["foo", "bar"] end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/iex_test.exs000066400000000000000000000005501254730255300237260ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.IexTest do use MixTest.Case, async: true test "raises error message about correct usage" do in_fixture "no_mixfile", fn -> msg = "To use IEx with Mix, please run: iex -S mix" assert_raise Mix.Error, msg, fn -> Mix.Tasks.Iex.run [] end end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/loadconfig_test.exs000066400000000000000000000025001254730255300252430ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.LoadconfigTest do use MixTest.Case @apps [:my_app, :other_app] setup do on_exit fn -> Enum.each @apps, fn app -> Enum.each Application.get_all_env(app), fn {key, _} -> Application.delete_env(app, key, persistent: true) end end end :ok end test "reads and persists project configuration" do Mix.Project.push MixTest.Case.Sample in_fixture "no_mixfile", fn -> write_config """ [my_app: [key: :project]] """ assert Application.fetch_env(:my_app, :key) == :error Mix.Task.run "loadconfig", [] assert Application.fetch_env(:my_app, :key) == {:ok, :project} # App configuration should have lower precedence :ok = :application.load({:application, :my_app, [vsn: '1.0.0', env: [key: :app]]}) assert Application.fetch_env(:my_app, :key) == {:ok, :project} # laodconfig can be called multiple times # Later values should have higher precedence Mix.Task.run "loadconfig", [fixture_path("configs/good_config.exs")] assert Application.fetch_env(:my_app, :key) == {:ok, :value} end end defp write_config(path \\ "config/config.exs", contents) do File.mkdir_p! Path.dirname(path) File.write! path, contents end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/local_test.exs000066400000000000000000000011671254730255300242400ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.LocalTest do use MixTest.Case test "MIX_PATH" do File.rm_rf! tmp_path("mixpath") System.put_env "MIX_PATH", tmp_path("mixpath/ebin") File.mkdir_p! tmp_path("mixpath/ebin") Mix.Local.append_paths # Install on MIX_PATH manually File.copy! fixture_path("archive/ebin/Elixir.Mix.Tasks.Local.Sample.beam"), tmp_path("mixpath/ebin/Elixir.Mix.Tasks.Local.Sample.beam") # Run it Mix.Task.run "local.sample" assert_received {:mix_shell, :info, ["sample"]} after purge [Mix.Tasks.Local.Sample] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/new_test.exs000066400000000000000000000125061254730255300237360ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.NewTest do use MixTest.Case test "new" do in_tmp "new", fn -> Mix.Tasks.New.run ["hello_world", "--bare"] assert_file "hello_world/mix.exs", fn(file) -> assert file =~ "app: :hello_world" assert file =~ "version: \"0.0.1\"" end assert_file "hello_world/README.md", ~r/# HelloWorld\n/ assert_file "hello_world/.gitignore" assert_file "hello_world/lib/hello_world.ex", ~r/defmodule HelloWorld do/ assert_file "hello_world/test/test_helper.exs", ~r/ExUnit.start()/ assert_file "hello_world/test/hello_world_test.exs", ~r/defmodule HelloWorldTest do/ assert_received {:mix_shell, :info, ["* creating mix.exs"]} assert_received {:mix_shell, :info, ["* creating lib/hello_world.ex"]} end end test "new with --sup" do in_tmp "new sup", fn -> Mix.Tasks.New.run ["hello_world", "--sup"] assert_file "hello_world/mix.exs", fn(file) -> assert file =~ "app: :hello_world" assert file =~ "version: \"0.0.1\"" assert file =~ "mod: {HelloWorld, []}" end assert_file "hello_world/README.md", ~r/# HelloWorld\n/ assert_file "hello_world/.gitignore" assert_file "hello_world/lib/hello_world.ex", fn(file) -> assert file =~ "defmodule HelloWorld do" assert file =~ "use Application" assert file =~ "Supervisor.start_link(children, opts)" end assert_file "hello_world/test/test_helper.exs", ~r/ExUnit.start()/ assert_file "hello_world/test/hello_world_test.exs", ~r/defmodule HelloWorldTest do/ assert_received {:mix_shell, :info, ["* creating mix.exs"]} assert_received {:mix_shell, :info, ["* creating lib/hello_world.ex"]} end end test "new with --app" do in_tmp "new app", fn -> Mix.Tasks.New.run ["HELLO_WORLD", "--app", "hello_world"] assert_file "HELLO_WORLD/mix.exs", fn(file) -> assert file =~ "app: :hello_world" assert file =~ "version: \"0.0.1\"" end assert_file "HELLO_WORLD/README.md", ~r/# HelloWorld\n/ assert_file "HELLO_WORLD/.gitignore" assert_file "HELLO_WORLD/lib/hello_world.ex", ~r/defmodule HelloWorld do/ assert_file "HELLO_WORLD/test/test_helper.exs", ~r/ExUnit.start()/ assert_file "HELLO_WORLD/test/hello_world_test.exs", ~r/defmodule HelloWorldTest do/ assert_received {:mix_shell, :info, ["* creating mix.exs"]} assert_received {:mix_shell, :info, ["* creating lib/hello_world.ex"]} end end test "new with --umbrella" do in_tmp "new umbrella", fn -> Mix.Tasks.New.run ["hello_world", "--umbrella"] assert_file "hello_world/mix.exs", fn(file) -> assert file =~ "apps_path: \"apps\"" end assert_file "hello_world/README.md", ~r/# HelloWorld\n/ assert_file "hello_world/.gitignore" assert_received {:mix_shell, :info, ["* creating mix.exs"]} end end test "new inside umbrella" do in_fixture "umbrella_dep/deps/umbrella", fn -> File.cd! "apps", fn -> Mix.Tasks.New.run ["hello_world"] assert_file "hello_world/mix.exs", fn(file) -> assert file =~ "deps_path: \"../../deps\"" assert file =~ "lockfile: \"../../mix.lock\"" end end end end test "new with dot" do in_tmp "new_with_dot", fn -> Mix.Tasks.New.run ["."] assert_file "lib/new_with_dot.ex", ~r/defmodule NewWithDot do/ end end test "new with invalid args" do in_tmp "new with an invalid application name", fn -> assert_raise Mix.Error, ~r"Application name must start with a letter and ", fn -> Mix.Tasks.New.run ["007invalid"] end end in_tmp "new with an invalid application name from the app option", fn -> assert_raise Mix.Error, ~r"Application name must start with a letter and ", fn -> Mix.Tasks.New.run ["valid", "--app", "007invalid"] end end in_tmp "new with an invalid module name from the module options", fn -> assert_raise Mix.Error, ~r"Module name must be a valid Elixir alias", fn -> Mix.Tasks.New.run ["valid", "--module", "not.valid"] end end in_tmp "new with an already taken application name", fn -> assert_raise Mix.Error, ~r"Module name \w+ is already taken", fn -> Mix.Tasks.New.run ["mix"] end end in_tmp "new with an already taken application name from the app option", fn -> assert_raise Mix.Error, ~r"Module name \w+ is already taken", fn -> Mix.Tasks.New.run ["valid", "--app", "mix"] end end in_tmp "new with an already taken module name from the module options", fn -> assert_raise Mix.Error, ~r"Module name \w+ is already taken", fn -> Mix.Tasks.New.run ["valid", "--module", "Mix"] end end in_tmp "new without a specified path", fn -> assert_raise Mix.Error, "Expected PATH to be given, please use `mix new PATH`", fn -> Mix.Tasks.New.run [] end end end defp assert_file(file) do assert File.regular?(file), "Expected #{file} to exist, but does not" end defp assert_file(file, match) do cond do Regex.regex?(match) -> assert_file file, &(assert &1 =~ match) is_function(match, 1) -> assert_file(file) match.(File.read!(file)) end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/run_test.exs000066400000000000000000000053171254730255300237530ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.RunTest do use MixTest.Case import ExUnit.CaptureIO defmodule GetApp do def project do [ app: :get_app, version: "0.1.0", deps: [ {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")} ] ] end end setup do Mix.Project.push MixTest.Case.Sample end test "loads configuration" do in_fixture "no_mixfile", fn -> assert capture_io(fn -> Mix.Task.run "run", ["--config", fixture_path("configs/good_config.exs"), "--eval", "IO.puts Application.get_env(:my_app, :key)"] end) == "value\n" end after Application.delete_env(:my_app, :key) end test "run requires files before evaling commands" do git_repo = fixture_path("git_repo/lib/git_repo.ex") in_fixture "no_mixfile", fn -> Mix.Tasks.Run.run ["-r", git_repo, "-e", "send self, {:hello, GitRepo.hello}"] assert_received {:hello, "World"} Mix.Tasks.Run.run ["-pr", git_repo, "-e", "send self, {:hello, GitRepo.hello}"] assert_received {:hello, "World"} end after purge [GitRepo] end test "run errors on missing files" do in_fixture "no_mixfile", fn -> assert_raise Mix.Error, "No files matched pattern \"non-existent\" given to --require", fn -> Mix.Tasks.Run.run ["-r", "non-existent"] end assert_raise Mix.Error, "No files matched pattern \"non-existent\" given to --parallel-require", fn -> Mix.Tasks.Run.run ["-pr", "non-existent"] end assert_raise Mix.Error, "No such file: non-existent", fn -> Mix.Tasks.Run.run ["non-existent"] end assert File.dir?("lib") assert_raise Mix.Error, "No such file: lib", fn -> Mix.Tasks.Run.run ["lib"] end end after purge [GitRepo] end test "run rewrites System.argv" do in_fixture "no_mixfile", fn -> file = "argv.exs" File.write! file, "send self, {:argv, System.argv}" unload_file = fn -> Code.unload_files [Path.expand(file)] end Mix.Tasks.Run.run [file] assert_received {:argv, []} unload_file.() Mix.Tasks.Run.run [file, "foo", "-e", "bar"] assert_received {:argv, ["foo", "-e", "bar"]} unload_file.() Mix.Tasks.Run.run ["-e", "send self, {:argv, System.argv}", file, "foo", "-x", "bar"] assert_received {:argv, [^file, "foo", "-x", "bar"]} unload_file.() Mix.Tasks.Run.run [ "-e", "send self, :evaled", "-e", "send self, {:argv, System.argv}", "--no-compile", file, "-x", "bar" ] assert_received :evaled assert_received {:argv, [^file, "-x", "bar"]} end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/tasks/test_test.exs000066400000000000000000000022731254730255300241240ustar00rootroot00000000000000Code.require_file "../../test_helper.exs", __DIR__ defmodule Mix.Tasks.TestTest do use MixTest.Case import Mix.Tasks.Test, only: [ex_unit_opts: 1] test "ex_unit_opts returns ex unit options" do assert ex_unit_opts([unknown: "ok", seed: 13]) == [autorun: false, seed: 13] end test "ex_unit_opts returns includes and excludes" do assert ex_unit_opts([include: "focus", include: "key:val"]) == [autorun: false, include: [:focus, key: "val"]] assert ex_unit_opts([exclude: "focus", exclude: "key:val"]) == [autorun: false, exclude: [:focus, key: "val"]] end test "ex_unit_opts translates only into includes and excludes" do assert ex_unit_opts([only: "focus"]) == [autorun: false, exclude: [:test], include: [:focus]] assert ex_unit_opts([only: "focus", include: "special"]) == [autorun: false, exclude: [:test], include: [:focus, :special]] end test "ex_unit_opts translates :color into list containing an enabled key/value pair" do assert ex_unit_opts([color: false]) == [autorun: false, colors: [enabled: false]] assert ex_unit_opts([color: true]) == [autorun: false, colors: [enabled: true]] end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/umbrella_test.exs000066400000000000000000000151601254730255300236220ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.UmbrellaTest do use MixTest.Case test "compiles umbrella" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project(:umbrella, ".", fn _ -> Mix.Task.run "deps" assert_received {:mix_shell, :info, ["* bar (apps/bar)"]} assert_received {:mix_shell, :info, ["* foo (apps/foo)"]} # Ensure we can compile and run checks Mix.Task.run "deps.compile" Mix.Task.run "deps.check" Mix.Task.run "compile" assert_received {:mix_shell, :info, ["==> bar"]} assert_received {:mix_shell, :info, ["Compiled lib/bar.ex"]} assert_received {:mix_shell, :info, ["Generated bar app"]} assert_received {:mix_shell, :info, ["==> foo"]} assert_received {:mix_shell, :info, ["Compiled lib/foo.ex"]} assert_received {:mix_shell, :info, ["Generated foo app"]} # Ensure foo was loaded and in the same env as Mix.env assert_received {:mix_shell, :info, [":foo env is dev"]} assert_received {:mix_shell, :info, [":bar env is dev"]} Mix.Task.clear Mix.Task.run "app.start", ["--no-compile"] end) end end test "compiles umbrella with protocol consolidation" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project(:umbrella, ".", [consolidate_protocols: true], fn _ -> Mix.Task.run "compile" assert_received {:mix_shell, :info, ["Generated bar app"]} assert_received {:mix_shell, :info, ["Generated foo app"]} assert_received {:mix_shell, :info, ["Consolidated Enumerable"]} assert File.regular? "_build/dev/consolidated/Elixir.Enumerable.beam" assert Mix.Task.run "app.start" assert Protocol.consolidated?(Enumerable) end) end after purge [Enumerable] end defmodule UmbrellaDeps do def project do [apps_path: "apps", deps: [{:some_dep, path: "deps/some_dep"}]] end end test "loads umbrella dependencies" do Mix.Project.push UmbrellaDeps in_fixture "umbrella_dep/deps/umbrella", fn -> File.mkdir_p!("deps/some_dep/ebin") File.mkdir_p!("_build/dev/lib/some_dep/ebin") File.mkdir_p!("_build/dev/lib/foo/ebin") File.mkdir_p!("_build/dev/lib/bar/ebin") Mix.Task.run "loadpaths", ["--no-deps-check", "--no-elixir-version-check"] assert to_char_list(Path.expand("_build/dev/lib/some_dep/ebin")) in :code.get_path assert to_char_list(Path.expand("_build/dev/lib/foo/ebin")) in :code.get_path assert to_char_list(Path.expand("_build/dev/lib/bar/ebin")) in :code.get_path end end test "list deps for umbrella as dependency" do in_fixture("umbrella_dep", fn -> Mix.Project.in_project(:umbrella_dep, ".", fn _ -> Mix.Task.run "deps" assert_received {:mix_shell, :info, ["* umbrella (deps/umbrella)"]} assert_received {:mix_shell, :info, ["* foo (apps/foo)"]} end) end) end test "compile for umbrella as dependency" do in_fixture "umbrella_dep", fn -> Mix.Project.in_project(:umbrella_dep, ".", fn _ -> Mix.Task.run "deps.compile" assert Bar.bar == "hello world" end) end end defmodule CycleDeps do def project do [app: :umbrella_dep, deps: [ {:bar, path: "deps/umbrella/apps/bar"}, {:umbrella, path: "deps/umbrella"} ]] end end test "handles dependencies with cycles" do Mix.Project.push CycleDeps in_fixture "umbrella_dep", fn -> assert Enum.map(Mix.Dep.loaded([]), & &1.app) == [:foo, :bar, :umbrella] end end test "handles dependencies with cycles and overridden deps" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project :umbrella, ".", fn _ -> File.write! "apps/foo/mix.exs", """ defmodule Foo.Mix do use Mix.Project def project do # Ensure we have the proper environment :dev = Mix.env [ app: :foo, version: "0.1.0", deps: [{:bar, in_umbrella: true}] ] end end """ File.write! "apps/bar/mix.exs", """ defmodule Bar.Mix do use Mix.Project def project do # Ensure we have the proper environment :dev = Mix.env [ app: :bar, version: "0.1.0", deps: [{:a, path: "deps/a"}, {:b, path: "deps/b"}] ] end end """ assert Enum.map(Mix.Dep.loaded([]), & &1.app) == [:a, :b, :bar, :foo] end end end test "uses dependency aliases" do in_fixture "umbrella_dep/deps/umbrella", fn -> Mix.Project.in_project :umbrella, ".", fn _ -> File.write! "apps/bar/mix.exs", """ defmodule Bar.Mix do use Mix.Project def project do [app: :bar, version: "0.1.0", aliases: ["compile.all": fn _ -> Mix.shell.info "no compile bar" end]] end end """ Mix.Task.run "compile" assert_receive {:mix_shell, :info, ["no compile bar"]} refute_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]} end end end test "recompiles after path dependency changes" do in_fixture("umbrella_dep/deps/umbrella/apps", fn -> Mix.Project.in_project(:bar, "bar", fn _ -> Mix.Task.run "compile" assert Mix.Tasks.Compile.Elixir.run([]) == :noop assert_receive {:mix_shell, :info, ["Compiled lib/foo.ex"]} assert_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]} purge [Foo, Bar] Mix.Task.clear # Ensure we can measure a timestamp difference ensure_touched("../foo/lib/foo.ex", File.stat!("_build/dev/lib/bar/.compile.lock").mtime) Mix.Task.run "compile" assert Mix.Tasks.Compile.Elixir.run([]) == :noop assert_receive {:mix_shell, :info, ["Compiled lib/foo.ex"]} assert_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]} purge [Foo, Bar] end) end) end defmodule Selective do def project do [apps_path: "apps", apps: [:foo, :bar]] end end test "can select which apps to use" do in_fixture("umbrella_dep/deps/umbrella", fn -> Mix.Project.push Selective File.mkdir_p! "apps/errors/lib" File.write! "apps/errors/lib/always_fail.ex", "raise ~s[oops]" assert Mix.Task.run("compile.elixir") == [:ok, :ok] assert_received {:mix_shell, :info, ["Compiled lib/bar.ex"]} assert_received {:mix_shell, :info, ["Compiled lib/foo.ex"]} end) end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix/utils_test.exs000066400000000000000000000076741254730255300231720ustar00rootroot00000000000000Code.require_file "../test_helper.exs", __DIR__ defmodule Mix.Tasks.Cheers do end defmodule Mix.UtilsTest do use MixTest.Case doctest Mix.Utils test :command_to_module do assert Mix.Utils.command_to_module("cheers", Mix.Tasks) == {:module, Mix.Tasks.Cheers} assert Mix.Utils.command_to_module("unknown", Mix.Tasks) == {:error, :nofile} end test :module_name_to_command do assert Mix.Utils.module_name_to_command(Mix.Tasks.Foo, 2) == "foo" assert Mix.Utils.module_name_to_command("Mix.Tasks.Foo", 2) == "foo" assert Mix.Utils.module_name_to_command("Mix.Tasks.Foo.Bar", 2) == "foo.bar" assert Mix.Utils.module_name_to_command("Mix.Tasks.FooBar.Bing", 2) == "foo_bar.bing" assert Mix.Utils.module_name_to_command("Mix.Tasks.FooBar.BingBang", 2) == "foo_bar.bing_bang" end test :command_to_module_name do assert Mix.Utils.command_to_module_name("foo") == "Foo" assert Mix.Utils.command_to_module_name("foo.bar") == "Foo.Bar" assert Mix.Utils.command_to_module_name("foo_bar.baz") == "FooBar.Baz" assert Mix.Utils.command_to_module_name("foo_bar.baz_bing") == "FooBar.BazBing" end test :underscore do assert Mix.Utils.underscore("foo") == "foo" assert Mix.Utils.underscore("foo_bar") == "foo_bar" assert Mix.Utils.underscore("Foo") == "foo" assert Mix.Utils.underscore("FooBar") == "foo_bar" assert Mix.Utils.underscore("FOOBar") == "foo_bar" assert Mix.Utils.underscore("FooBAR") == "foo_bar" assert Mix.Utils.underscore("FoBaZa") == "fo_ba_za" assert Mix.Utils.underscore("Foo.Bar") == "foo/bar" assert Mix.Utils.underscore(Foo.Bar) == "foo/bar" assert Mix.Utils.underscore("API.V1.User") == "api/v1/user" assert Mix.Utils.underscore("") == "" end test :camelize do assert Mix.Utils.camelize("Foo") == "Foo" assert Mix.Utils.camelize("FooBar") == "FooBar" assert Mix.Utils.camelize("foo") == "Foo" assert Mix.Utils.camelize("foo_bar") == "FooBar" assert Mix.Utils.camelize("foo_") == "Foo" assert Mix.Utils.camelize("_foo") == "Foo" assert Mix.Utils.camelize("foo__bar") == "FooBar" assert Mix.Utils.camelize("foo/bar") == "Foo.Bar" assert Mix.Utils.camelize("") == "" end test :extract_files do files = Mix.Utils.extract_files [Path.join(fixture_path, "archive")], "*.ex" assert length(files) == 1 assert Path.basename(hd(files)) == "local.sample.ex" end test :extract_stale do time = {{2030, 1, 1}, {0, 0, 0}} assert Mix.Utils.extract_stale([__ENV__.file], [time]) == [] time = {{2000, 1, 1}, {0, 0, 0}} assert Mix.Utils.extract_stale([__ENV__.file], [time]) == [__ENV__.file] assert Mix.Utils.extract_stale([__ENV__.file], [__ENV__.file]) == [] end test :symlink_or_copy do in_fixture "archive", fn -> File.mkdir_p!("_build/archive") result = Mix.Utils.symlink_or_copy(Path.expand("ebin"), Path.expand("_build/archive/ebin")) assert_ebin_symlinked_or_copied(result) end end test :symlink_or_copy_removes_previous_directories do in_fixture "archive", fn -> File.mkdir_p!("_build/archive/ebin") result = Mix.Utils.symlink_or_copy(Path.expand("ebin"), Path.expand("_build/archive/ebin")) assert_ebin_symlinked_or_copied(result) end end test :symlink_or_copy_erases_wrong_symblinks do in_fixture "archive", fn -> File.mkdir_p!("_build/archive") Mix.Utils.symlink_or_copy(Path.expand("priv"), Path.expand("_build/archive/ebin")) result = Mix.Utils.symlink_or_copy(Path.expand("ebin"), Path.expand("_build/archive/ebin")) assert_ebin_symlinked_or_copied(result) end end defp assert_ebin_symlinked_or_copied(result) do case result do {:ok, paths} -> assert Path.expand("_build/archive/ebin") in paths :ok -> assert :file.read_link("_build/archive/ebin") == {:ok, '../../ebin'} _ -> flunk "expected symlink_or_copy to return :ok or {:ok, list_of_paths}, got: #{inspect result}" end end end elixir-lang-1.1.0~0.20150708/lib/mix/test/mix_test.exs000066400000000000000000000003731254730255300220170ustar00rootroot00000000000000Code.require_file "test_helper.exs", __DIR__ defmodule MixTest do use MixTest.Case test :shell do assert Mix.shell == Mix.Shell.Process end test :env do assert Mix.env == :dev Mix.env(:prod) assert Mix.env == :prod end endelixir-lang-1.1.0~0.20150708/lib/mix/test/test_helper.exs000066400000000000000000000142431254730255300225020ustar00rootroot00000000000000Mix.start() Mix.shell(Mix.Shell.Process) Application.put_env(:mix, :colors, [enabled: false]) ExUnit.start [trace: "--trace" in System.argv] defmodule MixTest.Case do use ExUnit.CaseTemplate defmodule Sample do def project do [app: :sample, version: "0.1.0", aliases: [sample: "compile"]] end end using do quote do import MixTest.Case end end setup do on_exit fn -> Application.start(:logger) Mix.env(:dev) Mix.Task.clear Mix.Shell.Process.flush Mix.ProjectStack.clear_cache Mix.ProjectStack.clear_stack delete_tmp_paths end :ok end def fixture_path do Path.expand("fixtures", __DIR__) end def fixture_path(extension) do Path.join fixture_path, extension end def tmp_path do Path.expand("../tmp", __DIR__) end def tmp_path(extension) do Path.join tmp_path, extension end def purge(modules) do Enum.each modules, fn(m) -> :code.purge(m) :code.delete(m) end end def in_tmp(which, function) do path = tmp_path(which) File.rm_rf! path File.mkdir_p! path File.cd! path, function end defmacro in_fixture(which, block) do module = inspect __CALLER__.module function = Atom.to_string elem(__CALLER__.function, 0) tmp = Path.join(module, function) quote do unquote(__MODULE__).in_fixture(unquote(which), unquote(tmp), unquote(block)) end end def in_fixture(which, tmp, function) do src = fixture_path(which) dest = tmp_path(tmp) flag = String.to_char_list(tmp_path) File.rm_rf!(dest) File.mkdir_p!(dest) File.cp_r!(src, dest) get_path = :code.get_path previous = :code.all_loaded try do File.cd! dest, function after :code.set_path(get_path) for {mod, file} <- :code.all_loaded -- previous, file == :in_memory or (is_list(file) and :lists.prefix(flag, file)) do purge [mod] end end end def ensure_touched(file) do ensure_touched(file, File.stat!(file).mtime) end def ensure_touched(file, current) do File.touch!(file) unless File.stat!(file).mtime > current do ensure_touched(file, current) end end def os_newline do case :os.type do {:win32, _} -> "\r\n" _ -> "\n" end end defp delete_tmp_paths do tmp = tmp_path |> String.to_char_list for path <- :code.get_path, :string.str(path, tmp) != 0, do: :code.del_path(path) end end ## Set up mix home with rebar home = MixTest.Case.tmp_path(".mix") File.mkdir_p!(home) rebar = System.get_env("REBAR") || Path.expand("../../../rebar", __DIR__) File.cp!(rebar, Path.join(home, "rebar")) System.put_env("MIX_HOME", home) ## Copy fixtures to tmp source = MixTest.Case.fixture_path("rebar_dep") dest = MixTest.Case.tmp_path("rebar_dep") File.mkdir_p!(dest) File.cp_r!(source, dest) ## Generate git repo fixtures # Git repo target = Path.expand("fixtures/git_repo", __DIR__) unless File.dir?(target) do File.mkdir_p!(Path.join(target, "lib")) File.write! Path.join(target, "mix.exs"), """ ## Auto-generated fixture raise "I was not supposed to be loaded" """ File.cd! target, fn -> System.cmd("git", ~w[init]) System.cmd("git", ~w[config user.email "mix@example.com"]) System.cmd("git", ~w[config user.name "mix-repo"]) System.cmd("git", ~w[add .]) System.cmd("git", ~w[commit -m "bad"]) end File.write! Path.join(target, "mix.exs"), """ ## Auto-generated fixture defmodule GitRepo.Mix do use Mix.Project def project do [app: :git_repo, version: "0.1.0"] end end """ File.cd! target, fn -> System.cmd("git", ~w[add .]) System.cmd("git", ~w[commit -m "ok"]) end File.write! Path.join(target, "lib/git_repo.ex"), """ ## Auto-generated fixture defmodule GitRepo do def hello do "World" end end """ File.cd! target, fn -> System.cmd("git", ~w[add .]) System.cmd("git", ~w[commit -m "lib"]) end end # Deps on git repo target = Path.expand("fixtures/deps_on_git_repo", __DIR__) unless File.dir?(target) do File.mkdir_p!(Path.join(target, "lib")) File.write! Path.join(target, "mix.exs"), """ ## Auto-generated fixture defmodule DepsOnGitRepo.Mix do use Mix.Project def project do [ app: :deps_on_git_repo, version: "0.2.0", deps: [{:git_repo, git: MixTest.Case.fixture_path("git_repo")}] ] end end """ File.write! Path.join(target, "lib/deps_on_git_repo.ex"), """ ## Auto-generated fixture GitRepo.hello """ File.cd! target, fn -> System.cmd("git", ~w[init]) System.cmd("git", ~w[config user.email "mix@example.com"]) System.cmd("git", ~w[config user.name "mix-repo"]) System.cmd("git", ~w[add .]) System.cmd("git", ~w[commit -m "ok"]) end end # Git rebar target = Path.expand("fixtures/git_rebar", __DIR__) unless File.dir?(target) do File.mkdir_p!(Path.join(target, "src")) File.write! Path.join([target, "src", "git_rebar.app.src"]), """ {application, git_rebar, [ {vsn, "0.1.0"} ]}. """ File.write! Path.join([target, "src", "git_rebar.erl"]), """ -module(git_rebar). -export ([any_function/0]). any_function() -> ok. """ File.cd! target, fn -> System.cmd("git", ~w[init]) System.cmd("git", ~w[config user.email "mix@example.com"]) System.cmd("git", ~w[config user.name "mix-repo"]) System.cmd("git", ~w[add .]) System.cmd("git", ~w[commit -m "ok"]) end end Enum.each [:invalidapp, :invalidvsn, :noappfile, :ok], fn(dep) -> File.mkdir_p! Path.expand("fixtures/deps_status/deps/#{dep}/.git", __DIR__) end ## Generate helper modules path = MixTest.Case.tmp_path("beams") File.rm_rf!(path) File.mkdir_p!(path) Code.prepend_path(path) write_beam = fn {:module, name, bin, _} -> path |> Path.join(Atom.to_string(name) <> ".beam") |> File.write!(bin) end defmodule Mix.Tasks.Hello do use Mix.Task @shortdoc "This is short documentation, see" @moduledoc """ A test task. """ def run([]) do "Hello, World!" end def run(args) do "Hello, #{Enum.join(args, " ")}!" end end |> write_beam.() defmodule Mix.Tasks.Invalid do end |> write_beam.() elixir-lang-1.1.0~0.20150708/man/000077500000000000000000000000001254730255300156705ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/man/Makefile000066400000000000000000000004411254730255300173270ustar00rootroot00000000000000Q := @ build: $(Q) cp iex.1.in iex.1 $(Q) sed -i.bak "/{COMMON}/r common" iex.1 $(Q) sed -i.bak "/{COMMON}/d" iex.1 $(Q) cp elixir.1.in elixir.1 $(Q) sed -i.bak "/{COMMON}/r common" elixir.1 $(Q) sed -i.bak "/{COMMON}/d" elixir.1 $(Q) rm *.bak clean: rm -f elixir.1 rm -f iex.1 elixir-lang-1.1.0~0.20150708/man/common000066400000000000000000000051541254730255300171100ustar00rootroot00000000000000.It Fl e Ar expression Evaluates the specified expression. .It Fl r Ar file Requires the specified file. In other words, the file is checked for existence at the start of .Nm . .It Fl S Ar script Runs the specified script. .It Fl pa Ar directory Adds the specified directory to the beginning of the code path. If the directory already exists, it will be removed from its old position and put to the beginning. .Pp See also the function .Sy Code.prepend_path/1 . .It Fl pr Ar file Does the same thing as .Fl r .Pq see above but in parallel. .It Fl pz Ar directory Adds the specified directory to the end of the code path. If the directory already exists, it will be neither removed from its old position nor put to the end. .Pp See also the function .Sy Code.append_path/1 . .It Fl -app Ar application Starts the specified application and all its dependencies. .It Fl -erl Ar parameters Serves the same purpose as ELIXIR_ERL_OPTIONS .Pq see the Sy ENVIRONMENT No section .It Fl -cookie Ar value Specifies the magic cookie value. If the value isn't specified via the option when the node starts, it will be taken from the file .Pa ~/.erlang.cookie .Pq see the Sy FILES No section . Distributed nodes can interact with each other only when their magic cookies are equal. .Pp See also the function .Sy Node.set_cookie/2 . .It Fl -detached Runs the Erlang runtime system detached from the controlling terminal. .It Fl -hidden Starts a hidden node. .Pp Connections between nodes are transitive. For example, if node A is connected to node B, and node B is connected to node C, then node A is connected to node C. The option .Fl -hidden allows creating a node which can be connected to another node, escaping redundant connections. .Pp The function .Sy Node.list/0 allows getting the list of nodes connected to the target node, however the list won't include hidden nodes. Depending on the input parameter, the function .Sy Node.list/1 allows getting the list which contains only hidden nodes .Pq the parameter Ar :hidden or both hidden and not hidden nodes .Pq the parameter Ar :connected . .It Fl -sname Ar name Gives a node a short name and starts it. Short names take the form of .Ar name Ns @host, where host is the name of the target host .Pq Xr hostname 1 which runs the node. The nodes with short names can interact with each other only in the same local network. .It Fl -name Ar name Gives a node a long name and starts it. Long names take the form of .Ar name Ns @host, where host is the IP address of the host which runs the node. In contrast to the nodes with short names, the nodes with long names aren't limited by boundaries of a local network .Pq see above . elixir-lang-1.1.0~0.20150708/man/elixir.1.in000066400000000000000000000026271254730255300176620ustar00rootroot00000000000000.Dd April 10, 2015 .Dt ELIXIR 1 .Os .Sh NAME .Nm elixir .Nd The Elixir script runner .Sh SYNOPSIS .Nm .Op Ar OPTIONS .Ar .Sh DESCRIPTION The program starts the runtime system typically for the execution of one or more scripts. It is similar to .Xr iex 1 , but .Nm exits when the executed script does. .Sh OPTIONS Note that many of the options mentioned here were borrowed from the Erlang shell, therefore .Xr erl 1 can be used as an additional source of information on the options. .Bl -tag -width Ds {COMMON} .It Fl -no-halt Does not halt the Erlang VM after execution. .It Fl - Separates the options passed to the compiler from the options passed to the executed code. .El .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev ELIXIR_ERL_OPTIONS Allows passing parameters to the Erlang runtime. .El .Sh FILES .Bl -tag -width Ds .It Pa ~/.erlang.cookie Stores the magic cookie value which is used only when it wasn't specified via the option .Fl -cookie .Pq see above . If the file doesn't exist when a node starts, it will be created. .El .Sh SEE ALSO .Xr elixirc 1 , .Xr iex 1 , .Xr mix 1 .Sh AUTHOR This manual page contributed by Evgeny Golyshev. .Sh INTERNET RESOURCES .Bl -tag -width Ds .It Main website: http://elixir-lang.org .It Documentation: http://elixir-lang.org/docs.html .It General Mailing List: http://groups.google.com/group/elixir-lang-talk .It Development Mailing List: http://groups.google.com/group/elixir-lang-core .El elixir-lang-1.1.0~0.20150708/man/elixirc.1000066400000000000000000000031211254730255300174060ustar00rootroot00000000000000.Dd April 10, 2015 .Dt ELIXIRC 1 .Os .Sh NAME .Nm elixirc .Nd The Elixir compiler .Sh SYNOPSIS .Nm .Op Ar OPTIONS .Ar .Sh DESCRIPTION The compiler is intended for compilation one or more files containing the Elixir source code. The files should have the extension .Em .ex . .Sh OPTIONS .Bl -tag -width Ds .It Fl o Ar directory Places the output file in the specified directory. If the directory is not specified via the option, the current working directory will be used for the purpose. .It Fl -erl Ar parameters Serves the same purpose as ELIXIR_ERL_OPTIONS .Pq see the Sy ENVIRONMENT No section . .It Fl -ignore-module-conflict Disables warnings when a module was previously defined. .It Fl -no-debug-info Disables producing debugging information. .It Fl -no-docs Disables generating documentation. .It Fl -warnings-as-errors Makes all warnings into errors. .It Fl -verbose Activates verbose mode. .It Fl - Separates the options passed to the compiler from the options passed to the executed code. .El .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev ELIXIR_ERL_OPTIONS Allows passing parameters to the Erlang runtime. .It Ev ERL_COMPILER_OPTIONS Allows passing parameters to the Erlang compiler .Pq see Xr erlc 1 . .El .Sh SEE ALSO .Xr elixir 1 , .Xr iex 1 , .Xr mix 1 .Sh AUTHOR This manual page contributed by Evgeny Golyshev. .Sh INTERNET RESOURCES .Bl -tag -width Ds .It Main website: http://elixir-lang.org .It Documentation: http://elixir-lang.org/docs.html .It General Mailing List: http://groups.google.com/group/elixir-lang-talk .It Development Mailing List: http://groups.google.com/group/elixir-lang-core .El elixir-lang-1.1.0~0.20150708/man/iex.1.in000066400000000000000000000036141254730255300171500ustar00rootroot00000000000000.Dd April 10, 2015 .Dt IEX 1 .Os .Sh NAME .Nm iex .Nd The Elixir shell .Sh SYNOPSIS .Nm .Op Ar OPTIONS .Sh DESCRIPTION The interactive shell is used for evaluation, debugging and introspection of the Elixir runtime system. It is also possible to use the program for testing the work of small pieces of code escaping the stage of saving the code in a file. .Sh OPTIONS Note that many of the options mentioned here were borrowed from the Erlang shell, therefore .Xr erl 1 can be used as an additional source of information on the options. .Bl -tag -width Ds {COMMON} .It Fl -dot-iex Ar file Loads the specified file instead of .Pa .iex.exs .Pq see the Sy FILES No section . .It Fl -remsh Ar node Connects to the specified node which was started with the .Fl -sname or .Fl -name options .Pq see above . .It Fl - Separates the options passed to the compiler from the options passed to the executed code. .El .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev ELIXIR_ERL_OPTIONS Allows passing parameters to the Erlang runtime. .El .Sh FILES .Bl -tag -width Ds .It Pa ~/.erlang.cookie Stores the magic cookie value which is used only when it wasn't specified via the option .Fl -cookie .Pq see above . If the file doesn't exist when a node starts, it will be created. .It Pa .iex.exs After .Nm starts, it seeks the file .Pa .iex.exs and, in a case of success, executes the code from the file in the context of the shell. At first the search starts in the current working directory, then, if necessary, it continues in the home direcory. .El .Sh SEE ALSO .Xr elixir 1 , .Xr elixirc 1 , .Xr mix 1 .Sh AUTHOR This manual page contributed by Evgeny Golyshev. .Sh INTERNET RESOURCES .Bl -tag -width Ds .It Main website: http://elixir-lang.org .It Documentation: http://elixir-lang.org/docs.html .It General Mailing List: http://groups.google.com/group/elixir-lang-talk .It Development Mailing List: http://groups.google.com/group/elixir-lang-core .El elixir-lang-1.1.0~0.20150708/man/mix.1000066400000000000000000000117641254730255300165600ustar00rootroot00000000000000.Dd May 27, 2015 .Dt MIX 1 .Os .Sh NAME .Nm mix .Nd The software project management tool .Sh SYNOPSIS .Nm .Op Ar TASK .Op Ar project_name .Nm elixir .Op Ar OPTIONS .Fl S Nm .Op Ar TASK .Op Ar project_name .Sh DESCRIPTION .Nm is intended for both organizing code into projects and their maintenance. For the latter the tool offers some advanced features like dependency management, packaging, preparing documentation, testing and so on. .Pp Have a look at the .Sy SYNOPSIS section and the second way of running .Nm it offers. The point is that the tool is none other than the Elixir script, therefore it can be invoked via .Xr elixir 1 in the same way as any other script. It's useful when you want to run .Nm with particular options. .Sh DIFINITIONS All the .Nm functionality is represented by a set of tasks. A .Em task is a piece of code written in Elixir and intended for solving a particular problem. Like programs, many tasks accept input parameters and/or support options which slightly modify their behaviour, but others do not. There are two types of tasks: those that are available after installation this or that archive .Pq local tasks and those that are offered by .Nm .Pq built-in tasks . The .Sy run task will be executed by default if none other has been specified. .Pp In spite of the fact that the greater part of .Nm is tasks, the man page doesn't contain the help information related to each of them because .Nm is self-descriptive. Thus, using the .Sy help task, you can get both the full list of local/built-in tasks and the information related to a particular task. .Pp An .Em archive , in terms of Erlang, is the ZIP file with the .Em .ez extension which contains a precompiled Erlang application with all its dependencies[1]. .Pp An .Em application is an entity that helps to combine sets of components into a single unit to simplify their reusing in other systems[2]. .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev MIX_ARCHIVE Allows specifying the directory into which the archives should be installed .Pq see Sy mix help archive.install . The .Em ~/.mix/archives directory is used for this purpose by default. .It Ev MIX_ENV Allows specifying which environment should be used. The .Em dev environment is used by default if none other has been specified. .Pp Sometimes you have to use a particular set of configuration parameter values or perform particular steps when you compile or run a project .Pq or in some other cases . The .Nm environments allow grouping values of configuration parameters and steps to switch between them by specifying the necessary environment via MIX_ENV. .It Ev MIX_EXS Allows changing the full path to the .Em mix.exs file .Pq see Sy FILES No section . The most obvious use case is to have more than one copy of .Em mix.exs in a project, but it's worth noting that MIX_EXS should be used only if the .Nm environments .Pq see above are not enough to solve the problem. .It Ev MIX_HOME Stores configuration files and scripts shared by multiple .Nm implementations. .Pp See the .Sy Mix.Utils.mix_home/0 function. .It Ev MIX_PATH Allows expanding the code path. If the MIX_PATH environment variable has a value which consists of multiple paths, they must be colon-separated .Pq for Unix-like operating systems or semicolon-separated .Pq for Windows . .Pp As has already been mentioned above, there are two types of tasks: local and built-in. These tasks are always visible for .Nm because the directories, in which they are located, are a part of code path. If a task belongs to neither the one type nor the other, MIX_PATH helps you say to .Nm where it should search the task. .Pp Use the .Sy :code.get_path/0 function to get the list of paths which are a part of the code path by default and the .Sy Mix.Utils.mix_paths/0 function to get the list of paths specified in the MIX_PATH value. .El .Sh FILES .Bl -tag -width Ds .It mix.exs Contains the most significant information related to the project, such as its name, version, list of dependencies and so on. As a rule, the file is named .Em mix.exs and located at the top of the project's source tree, but you can change the full path to it using the MIX_EXS environment variable .Pq see the Sy ENVIRONMENT No section . .It mix.lock Allows locking down the project dependencies with a proper version range before performing any updates. It is useful when you know that your project is incompatible with newer versions of certain dependencies. The file is located at the top of the project's source tree as well as .Em mix.exs .Pq see above . .El .Sh REFERENCES .Bl -tag -width Ds .It [1] http://erlang.org/doc/man/code.html#id103620 .It [2] http://erlang.org/doc/design_principles/applications.html .El .Sh SEE ALSO .Xr elixir 1 , .Xr elixirc 1 , .Xr iex 1 .Sh AUTHOR This manual page contributed by Evgeny Golyshev. .Sh INTERNET RESOURCES .Bl -tag -width Ds .It Main website: http://elixir-lang.org .It Documentation: http://elixir-lang.org/docs.html .It General Mailing List: http://groups.google.com/group/elixir-lang-talk .It Development Mailing List: http://groups.google.com/group/elixir-lang-core .El elixir-lang-1.1.0~0.20150708/rebar000077500000000000000000005016041254730255300161440ustar00rootroot00000000000000#!/usr/bin/env escript %% %%! -pa rebar/rebar/ebin PK/SBrebar/PK/SB rebar/ebin/PK/SBOv-rebar/ebin/getopt.beam|Xyxյx$:#dQ@6 HN ז-@ %ˊĖ%g q ag Y=mmPx,}nˣtM?~$MRGs9ΚW/w^u^Yʏ\ 5P;- %O!=ZfGӹ~Oip4͓͏zbhvk{j[<[cY%ٔ.fw8|nKvǦ\X?lP4C O!MCٛh[N Ci$^%wit,ϦbM枺Z%If&Pf ,aRzlBT#ّ쨞m4HdNb)C#23$ʕѺ|~85 tF?#P.3J,m-ҎBMtɝjrb݋e22*XESePKPab8-;Zۗг$"vw4:4p"Lu˗0WhXV0ɸ LMfФg6KȮnʏKMr73; @iTJoĿߒ6 Klniw5W3l)ϙDpAgRfHީ%`v3#x&rw$DZDŌױ! vj֦miRNy2B:7vL{ uY3*!;6xNiPMӡ0}{5 s5w547kOdP5e?Í" &B LH)8~\5Tޥjf~0rl?n&D.LUMc.h>S莊II)Gգ`Ƣqiظ4LZ&S {_M{i-~QE'0*$nUOd`MQ— m~3gWb9Y"uԄR`7Otk|<.i˓أ&i5bY2ri ZGuHP> Lf5 _=R7,`HE4$,ǤgC٤-3go1OV5q' + a3 M'Z-lU>+Ͷsl uMas)eT(ltvN/;`4;!*궙bnɘq7% kF"4M-Zt,6 FlqaUttN SϣXv*x|f;lo 8;N F02hi$\DQ], 87%6k)KpE7Tux*e6HI0%5$IV(R]IO| BwC !_j)Fa12Mq*,])ifˠ|_\&2Y,nֵ沣J]\NŶUn  HpE ݧ)aJ4\᠁h^'CzZP,@DD ݃`_5|oeB ZO ՎVDEo =$|gЉOGrv: *+: w|\W؀|ZV`faN;BG: |}C+cHsqaJh QXfq[yASOC>-~ @n9sLufk$&V^R}_>?Rɘdn٥`Ev8xglI;[j|Ba:opm Yf p=oW~8$ܩF{9.tk\˩mv%O&pa*q\Oq=$jx{ [YRz6Ks PupufWag;szg}D_-;a] v ˴v) {$/Pأ1!p6K*8IѰi=eE|h*[cPunt65r cKZL ASďh6YL?O:nş 6BQb笃So8hm?O|xJ=IE谗s5h/Nȍe!M| ^wTLp\M'-`^vz4֌6¸ֲR__Ϧ{7}٬$(|Sn\kՠGѭӅkA LlGXRmn,z]‡X!hm c؁vB{-Jgl vEag 8P 8q4m6-}N+{20[C2< <09 '0ޘHtn.D%&2 ?uZP!h:xd.aus) + csnCm6Lq=΍H1B@8]cT$BN/ |y4Rq킉5:YDA$tͯ`lVk 쥩C;pd+ ݟg^5V߆8o+ڸ+k7|Ua#ڤV5$Ą#P8W-sOe"V$ pT;#?S]־JMp +r6YZZIjkuKol">fi B-!;R߉WW&l ^X<bU|`mT(U5\6 S" mK 揄TC,k@#~0jށOd2C^MK_=@#hWnR`wCjВ2߳ٝP2(s4̿B@ ]30? Mgh6 ? ?4qQdOPXQ|:(jVpQ'&$@[07l]~o@7H? 3otZ045I܍Zzݲ`R`3)C7 Y7,{f@ޕp佥MV$n;=5Z?%+qx,-0}fzDW˷M W`"%wwSl}af)W4 \It}8Qf&u`bvy/:o:CݑOp݃WeU@X6{-n_,5/;58kmҠR$=Ljl:rEJi"b< B8*D}z(g6{A>_hoc<\`F!F$ 3ap[<9 fhMܭ_FćG =YGmI=L#+?W!3_GciS~ B9- Ӳ}%i3v`7?OC* [h~ѳS.efw+V)m)D? Q'*В7Ǐs]}܄MTO?QJar5!3h_~)#"8HX:Nҙ"?d:\R:X_;i QHtFj,i'_Ug!mT pӝ[ǂO1φ[ڲ% ms,0Ɔ-KœHK(# --S b^Ip& IB@$ oḨےnjRJyQUE+p,ޘ)˶9˶%KgmYo~إ5˦7g[?K,Ym_:2l6^aXrX\vS Fi `]yOQ`~pBLpz[*Vp3(?,/s_,|93|6~"nPN@rU~,/:I@}9\C9Q嬯nY/g d1E\T9.2o5Uȼ!Lf%d9ˇ}-sr[aR v;t-&HC^{Ua6` ˹Cu2{dp`s_"HogwwG}N!D{aE=Wff7'}`OO$po@Jt reVo{0 h7dc%8ńܺtE}2%LV55U ~]%PK+m\K(U^ҟ*tD~jMזj;$%+j+Lz0 {0#7ƻʵI0EMݑ+H2VvDwlO@mгo Dvc G h5jAFGh ڊAn} =It44:@GЛ-Ot@Ї؆sdKp).8&^WfGmx+x;__ûs/Sx :/72o;6Q;uP":4hEgS7-tP/5%tmMtm1v:H0Iw} :B(=FOStӟWizF_wDEo[d˖bV5*,lyJoZk)˴ꭰ L% PK/SB&c:rebar/ebin/mustache.beamX tS}{<~6eKlZ- Vl/,=²JlliR7'Bɖ&!aK Y6)[t'+vWO϶=g>tf):ҝ2L0^4Ni&"QJ4 cyɔMg0JD{JR|_`" :i\MP<,&ʔ`80 ftT6R+&END!=)cay2y b GB)T&SqE΍Fi2Lؒ"tG _W++J\A*Xl0K'KC)6@R"X~BHTK<3J"xfic,dS,xሒ{t$4l-:s$- &H(H5T@3#ȄY%ӊ&k"5mX@C(c|j 5lL4iJJSJZΝ F@eXJy"tț+<'C!A%/.MƗQ;5pWx&|NA9o[٥Qu4cUQsM95Ӭt//h#&L$>"xVk.Q:yu>˃xܤĺ.eɿ񸔉%-# B#ru]˒wm!"sIzgބU8uz萐;"+di |LEFRJ\ڸBsT'FĖb@J6a{Uh3vn9mD!]|y>o \̪dZtJ7?PV28"&ZDK }>8Xf:bc1\1M1Ō`VidJa'Wju n+úPǕf+;-A"vTm`j(2M@ ~D_b /` t.%ޓ-7W h$m VV .-0[ujl]!L)UNn8!f;! fsrvmgFv> O'yI`$Ew9Nq8sE #I$d$ rïJ>#j4RDgXa>AZ,*ʠ(N*$`{JRvO8,=a{_ѧ|&G RZ+P"9Det쫃^ Fpr]`dW]9G d+h(&V pX\w ٖ B:ts]TUwRޡ)7ym:^*ڙI@gou:A*5kE2fv\_1wquۀ&]Fv%x**MO$U;;sK{8c@ 3fI0 `1>0^E* @CMa|GҏE6EҀ6۸XM@@ !O|40݄:QhaeiN/]=x=7r#tߋY-Cn>02Ì,b*2+ a3:!'pm\[e@[Uz *ÝUBȡTjv }@=ɀ`.&i B0#)O&`6p# <&F0f90ap:Ku~Wt A[c.%R+9Xcu-fa}*BC1wϟβQ`t];`fa}j3KKP3ˆ >ѭ㩏hг,齟9 c >?o} NZ9Bs\?,+H~@$Ekp|-w|M7ȶ?7|_8_x{БeΙO~KNl=vy\w]?^rԹg?YPnB|+~^`Ǿ]~dw~ݴ},ݱUcK[~#'Fw4:=z?z'wϝW^kn׼ׯ1ȝȿѿ=w?ۅ|/ޏ^޹koc&7w;nZw|ߚ+]ިz+eE|SC%>]c6{Em-=t3}i>VfE/2>SGY9{sޛӪ{n.gwsxCL]ç~m:MAioGjtiU:}L^ѝJ)0o<;9aݗх!3g]ׇr SQ\t\a YѧT<ְMVb<# {[n Hggx:<<Cd1Ebh:,ş;YÌ=?oaؚ@sh@` S2I-͍"74 SζPD}=hps[Dg\GSYy:o0, ZZ͏d<i4 }r/|I'JSR 5(+ѽ5LїoſS0fh" p9UZ܀m`;v6.܉L`/Ǜ>Ə'>__*>Ogi,~KG}{'w; PK/SB@l rebar/ebin/rebar.appVMo0 Wr`zJa"0dNɒ,>6M|4EQy&՗TKU vqhc /ѫiG}z OӔ[-u\ 1PYm דgȏ)炑_J&Fзk P`7#5md֭5a¢n1 VSɎ0z,0"#JM3su{ɑ4w+X(S}qTN+krDœoUK+$q FbqYojQ>sN%:עqxP:#alh7ʄ$7TeƱky i̠"/8c)xR8dRPtSrs=Y -x`sq$cK6sH?PYDʜ\"19DBrLVҐ 1 襴c;H)]p x@IBQ" {uQb=Kdq+)5ܿoWPK/SB!rebar/ebin/rebar.beamY \d$b$'4FPQ\!Y\QVԥժb{ZumVjHm^Bj&rw2gw93P#\WD"h-5:%Fv[l^=nob:d0Zbݷ6IpX-eFnXFkWfw )7Z],ڌVp-VBVn1Yc5N`FZb;b/b-ljVRiؤj)Y\`hXN[1yXf+c3k@fKV ߡb 2up^&ej\6CoY#e]eN0`RceSL`8PpS[s>.aNe~6_ qͬat Y58F*&Vo._Kve33_Zp~P7aYjw2znԇ/jt P>*ӫJʭFUabjc])z<2Af~&cp92kóTjY3.pN>vB6n{ksNZ[vH/XJ@O+m] C5ǐSN-`3YLfKYgu8abj}K&?<)v镁qݽ]G&J\NiELRSשc+k_f5z\lX6 qÚV k$ PX W'@x{5.ʴXF'~)5(T.UP*R ,Ҩ`&L%xPIa(,QQF1T$Tի  .T+ ~A`F\^.voEAqa,p8FYQP KB b`-^FGq(i_.,${̪*N.*4*@1|a4 Z(պPR.3L9~IW`2,~cS? +eP(w3޶ o:wUs(2Hǚ{Jk TRQSZyB3$% TD%eL1E#  !(JbT$hb94Aia_HRr*CNF2-C t@ v!:ӝ^^dWIl^EN'בe@Czd$l$$@4b~64JG~0{uc`iD4*??_n P [:srDi{ʡP,(8 Y6Zh4`AoH(CáAw hm  M I'7B3J;]A+*= CXu(8vL8ఄWxk[SV M,p$(X8*@U*׃394(r4XP1ŬIJa +&F{G-'Ԩ=xʊ_DheH7 0;C {(|84 Ä: FdVW@A 5@˻d! d?`ɡR8 FΠW6Fmq#0 -S#p j,a= 3fA#S 2~z=ꢗғr= %+0)o%(>qAuA_(ŐZS$f +A#u$JW%ejIj%k/hj)^vP{Q)DK2FCV ^f>;&WTf#TLt@&p(C52auz0xƯ(m$2;W]ɭdtT_ɤ~ 뽠0:@wx-UKk]˴Gݟs2 hix2N tx%55F*!,50+QΆ VS nq= M5f{s=5GKŰX *<!PS<68c7C`I5HA2@ `S $ h\|@b%$\CwףhEp(R_@e\+&7t.[#CZj)'Gj<&@R $u䰏(A{H!`>H΂NP M  /xlmӏj:$>Bm':脸)@$?@clL;>h|k;Hѫ9 4F1?^ ?ZXqcv|i;[\v,g ǟi@p r\TAx8/:E,<al`'} P{!䍂 UrC-n%M%vc'd)j-?eGBzwy.oƏz|OUa:Fjw'jچ{o6a7mI7_?l^"wēUwxl}_C+wg;?8dgCJ$ja³8$~2`W}usN6]O?'q'د~yKZXgilov=0gQF}'HrxCpaDԠ}fC7馞Ot6U/rs9V:Z31(9~ߐUCɖ\ful߭y[.]ףFo~ݜg;p ovveri󏗟gn|鎁|x{`oW~0o #/]ݾ $j,GVś./\4bǨ?~ܶ}~kTp6<}2K|zCQBͼA Gcw}"D1#ntIEӇNVصwyt?oٹC٣CKv={IgMtXύ<"\5 zɖ!ϖ8:F4Qq3gW\%n x.y{?tߠZy%iךg~j-}˥5͏w,2wo@ .JwEՅd뛟uЅ\Lٞ|Dπc z Y.mBY+rjOht%԰ps-+֕$5ίN.3 ]{uZ9=dNG7F?nɅ[CT=l{G^JSiƬ+ ~nOrn|a,^ϊmlXysj}ó#+ >Hdf7h椭u^Q];ۊMoV~xxߢ'7n{Vq#cvzۺ7'H~ڿ&8쌑ޑ׏̊mm==i\mY`.aKwt30HʏäW*O92vHVsEkoMؽisd׻UYM697B{׉mt1,qs_ 6,Wۋ4:˃Rv9t q-:{Z&sn{KQ*M.婣ƼĚLI<{DiF:'j&zS$}˘#M(?pdeG_2ᛢy{wܥ]eT̺٫ﻺzE9G4s.zr}rһv!vnvna; [_"ԽO,9w:oΪq6G.h*NI?z4*4x홫#~8G`Nzv%I6ތרM}ZݿW5yuGsc slpꥇ'v |…OJ Oӟ49X.|8CL[?~,X}K뮹<ޤ/w3oE[][mG+fÓ:5;JUgά4LeO-_o+=1}z^;#2] 2΄M=luυ~%<{kgҤ_o<Ճ^YJxȈD(.nz3HȠ)Krf؜_ǵC|_3qyu{{U }>-=h/UǧH?؁5%oJym{hP{';d~Og]/әn6W w0=d >np;T wapf 84wIG 5D{ }OnOD$E/6Zq궐EKv`*+3smpg#y} ֗ b$^ .OuY|IR KKHjY=&$z'r c&HQ;40*7?J)QIRS d9Ґ;,gx(lq+58hq澉2mQP7pU=HqzLtj(j!cj=ϻ=ϏphB$'9D7 ?@"\ғ?xYK:"&93dӜ0Ʒi\]d69^ :sŪC+d'\'`'㶶s7%LGcLF9#'mF!TQ=<'<:i DQb$HI7yKzxkK?= bFg0򵥨d<NaصC^~ϑ-p,fLCT;#@!+5f#֚$`iADAYnv~Mz8"]GHx mĺ^ p~:6˷ֱ[w8p^hNN;F@~nX?UZ6t:&gkڔ1PUFq!Gl@ VtmA_:O.b[ӗ_]y x`+WѦG7=ܞblǾϞe}μG_>ՓO} KM=a|(~ҕWM{e7cgl;[+/|Yx8O6|+|i9'O޻Ⱦcū-=sפ|' `//s זo?;z%Nzkl.=-O9c_ޚ/{c홎ⷮ @ݳ33Ԝ%iꬭ;:@s>֝ :gG;>5 ͺ3Ke•G䔮E/^.<뾺nLN*xʊfny3z\+_QRVV, !WVrj^#l)?A/G"Z-ŽD" H"j +%D`EbDd;FN4u(oҦ>%i:p/"w랮e ,Mx̊ŀ]fQE͋SR4]g4Z.-9? fu:!eO`%zf0ez1(sy<3ƈL3 290G PK/SB@2 <rebar/ebin/rebar_app_utils.beamuWln9眸MZM79vi9qGR$*hؗԍqC[趲N)K.1* R!M+BcMbe?{K*aݽ{y8 s\}t +rqzCObqRdKLj3Ʋ2;'h4d|2 G [8/MFZ(f"-5a V& xHQP(#PndI_nF ɒPt^/eGaJB H6J3|niÉR nT mˁEi*S,i`|Ztmld”/B Q]WYL2,Qԗ-aJ V׏TRu#WZd7kRT[LLdb }MLv`庅..XTl}:h2RܸnM. pak2[OfET1ڲ\!]꣙DcWu|Ύl( wuƚPXt_Bd i2KL 2/a+u`UW#9^5UJV(Fp1g^ Y^\1/9>:Ic2 w*ڲI/ TY! 2%RԈ%NUNpIjF^'),-(WtmDt{5ߚ(7'򜤩q:CL@3OD0T KDuNʐwSy! 7Abѣ<,n% nn\LF0|ZDZIA$*Ґ"'d` r#)I@HX)IWTI $RyrT")?V)_$ՂDcf4S}j$ ?%)&mA8[&f U/dWtmj$KjAW\K(J' Ѥ$5ĵn]-_V-qI6T.t-w`zIAz5>+q8?ExUTB@|Iu1,3!%p~(s͵g NuWØ6EĆ4py!YD^j۠_U *}\^q{6_Gԁ ""J) wEŶAiV-4}TytS4YX^omҘUצ17q>7tr;m\JcN*I^;xΉTp( cIC=VST'TO@ C]% I܃nD8aO4iN p*tnT.fYq OUE}[dC nFzTk;+ni-X[g#6vPݽGM<ͤ=s8{N45#Q/OV1c96v{!#H96 |6YM p="[ܖKbȄ_6po~ D5 <|9jD;cA7mh=K쵶[l| Z;f=ێF[lcg -vuz$b Nג6>͎_ƥ=~kȝYo:b ~>V[_m85r%_n.ss9ve8P[oG*=tϕ4}X~󍃧ktT/ozwu]ׇ NO\{ێ=p/8~myM'_x}modv1|g'?~=#?U't{oο]ž'.|:ܟc>yj=UH|5kdAlm=mm[l=b Y+ \̢#j%n*\ܟ>z{wൟ{p~|x㝅uA3͉=hT1 -Tp-}zWߩ#jWgh;v.;;5OfJg0T;D;&{R{}ᮁ#i()& &39p8 dm9NnN[(*FJ₡%J'H6y,dݍBp r mHlTƅ n7ҋn`,Tf,ºYe v=l}`w0M3U8{`_gQ6˞aϱ'{~^f[w6yPK/SB*0 0rebar/ebin/rebar_appups.beam}X p]}Yk8keْؖ'kٲ|8iJȲve+%uWrR 5R)eJ!@[:I' LK;i; ïP@ e2:3W{}~<&,Qd45zZ{J!2j:M(I:攢[<#ĕV2=$3EtIM .6Z"ʡ QL\i޺sˈuӒs'cm^w3!^x?mw/v(POWϊBz Y%9M)VT5rb[ t sTOp:Wdo,B ] T`ڀ $~c8 W#d`ɅP>lZ_z2zxA78~Nd(zWr-B\~4y.p'y !:,  (Va^Ds@,p V(hNt՜Pfvxta H(|39gF_$|sAgEv/XNN uox),!ᇄiqcP.y$)!dU8I!90/٪AesZr:I8Op&3p(r1A5w_{Dh1A+ 0+u$&ǩ^`V[KTݼilr5Aago3 zR"7|a>,|}x I`a qB'@ZcH֘AAE9˯%֙`xF`*8 :0XGJc1?Sa >i,-N 2CAPK/SB/f3X #rebar/ebin/rebar_asn1_compiler.beam}V}l?((c#gNlQCmAʔHɴ%R#)7H,M-hf͊M k(.m-k,6 @Qlmw4X1?޻{IvOޛ/ :f{mFX6 Yo|%AKK} (4VdQ5Ej5wǏqa-pϾ>ײo8s9t}/L/ħ#?;f^l9?.&_<3kޭW0#>H/[đ,`dBH~"gQ'}s3kZ^ bV'*)%堶ãFe//CM&wfXf<`nZST7 U膦BSU;:*̽!bvAl}rtp׵` Tڕ]aM̓^/̨ʂ)ԔV9W(,ypx^)ۧb||G(7?Ə|4_g4?PK/SB#rebar/ebin/rebar_base_compiler.beam}X{py]kxHItAO䑀k )A$P8 @IadݦU:kˊ}(2'<`f@X'x32/3Ivخqžknk!ABc.OJr xvA3-4KH,Xc %XXcIQC,[eC4!3yRWAᦴxK-q(Z'{/PqƁ[\+JƑ;󞄸lZY ӊx">rH`,`Z%4w"lLoK[)N0 flq0w0Weƛuw&CR&" Ѕo *pE}[MaWH;l0ô!- OeLIdigBc0~qN7Dem n⛇PuE wU`,ӝ(1bKwn[(UGGMUeiNIӲ*@)(VR5-:BwxBU;wmn6q~@8?iך&}7@>٠ހpG;xGmPL;ct haAHB0!~h0zJiNDg !+>z@{;龈c sb|_#۾8wȪ>H8(.\rfU |_?"Y 0hj wDpgE0Pp de]Tpة8Z4dp/8Hp+*s ]}V5$ UUuB; #bq&=`Gm<[OңL)LOXF!G`AnJpw0㚓yixXxh̨2 3im ^ Oܯ!$HF"#"v ٭IiM$Gָz?:1Qk-cń6NE?yQ)pBF;Xic 6tB,y zդ'xrF60f ~hxBM  mQj\qELNE]#xbO1Lg!T: HIRr8qN%'asᖉgu^S" @P6> ݧ/js4YUN!6<ϖ'C$>x-@7Dh@!8P4!EaOj݈9nsg]`taiK6>/ _$V2KqG4mw:?dp6i "Qvcn7"\1i*J0o<8[-F! 00 ;*So[mxa(ޜwx<[<;\vj|;[#|/}z|>8ܲ~e}_:Xog|>qc+<8sF9ebO=Z&U?L{Kn?,z#SR1>}ʵ??F~o/<~7V^?5Rn՟}ٞTU^S?_~eړ 3?W+~7o{_o~̗2mcY|xH?قOow^?}N];oF_x%ӵC ׄ{W_FG Է^~S/~^~ѿ]g~O K/7'9N!U+zy{ъiɂqܛ?o+IO#͟q̛1eO\Ǔ˟Aoż9|u[5ۛo1j< ccӱF亞ъ R]/<+u⢐Mw%B_h5+y3kFd. /UXZj,E4EcT5 hŢJggNN, >80bkL\"<$l/5ԁ^n=X`a(_Lח ߗXHo?_C0o͹ NzK@Y e/]]s:B'}kűU8W8&{I? Q2Dcd$"gH%y%yr̓EDʤF$Mr\!Wgɳ9K/_!ȯȗWK?"L~ɷȫ&S;/ [;>}>O"?"$?!MR$$ [PK/SBaG'Prebar/ebin/rebar_cleaner.beammSMoG~_qB6D( 㐪u$8!ޱ=zך ɍ5p@i[* ā Bj#fˇH<3<;+ll +kec)Q[LD"'Ymcٓeq 'b`۱cm ٶ.2,TkNo鮁T(i~&Og+rY)+ߨ6髤M \tD!ãHRDOžU'$P8 ()l( 3eH+Ϋm"SM86V(*CObS#Ó6Js"JuQp>FRL5)gk6o0d荇ks8>ǞcCZ;Vh6o\߯|/OIo?ͮ!Dٜqnׯg|jf.p"eۙ/wy<>s8d,~v UEe!kJՁ۳`c Hns{>f>?f l/tBXD~_#!jIxĦ01l WG:$\SGml"3]ꚺSރiY*,J%Ţ)~cu[lnlT;+쀠la,ZKM}{kzMkA[|wpuM?ZT;hrI BM󺶇5C;_)oV?qܴTiJi$÷ˤ )Qٯ&PK/SB]rebar/ebin/rebar_config.beamX}l[uO'=wC_'D(Z(#k'E|";MbA, WWwX7Kc,bE,mu+ -t }b3ss~9>unP~/ʫ ) uTl5+ Yz-r-J%v׽^+-/=o)fRd%LJ\)EZX7j1[Zn5r03sp\@fM鮲$ˬ͢Y3}PSyjEk3ʙBf.Ui5rVVd̚Y],[&uK)edf|^< ,f_*M)eWMj̒U(Z/ j.׋jRhZnxʮ攋gY]UM[LV LPmvCob^6eu1KGk7-B,dC(7[gL0687mKLMOڬ\PuV2wG4[yUlUg8RˢEq'JVR/rfY`Afύ-lMy4.Zz)۳|#dgBb <`Ee0(MA;φ܄[izTE1R5.jxVMQD[ l+(A^1^{ʪ!u(e&kMeBH%՛NyRJ]*헁 C66f(cѺ4R$qIs̾81PRCY)EMK7sȜTq#jR:fsjX0fFB?u$bZ|.ӦM_.~i"+P6nE5ؤӣNF1uM$t&]@킽+*UXTw 6Q' QŪ&XܭdKTފ[sڊ4zևX{q-HJ%ѫ@J 181zl҃=o ;T߶!yCӁr n*7 v)UAyGM~vrT=Ļnw!wk(IbXY)"ٱIѣNQ"w}U Mv~z.wNNMvg&[oOT5kPI?$&{ݨ6 y/;Rߠg8B9%Q<R 1?;8,D  ^'qztyO{;ɣXDz6iMW Rzqd/*6taUg1gW!.F%`;(d 2TlW'&B#[Ut&h D>נ}.jԡFM?6W&}@e?*uq: pWպM:첈!j@am1rMp#p#4lUHqGu98:GDrqaUC8e}taPsL0-!v@^vҋ""kˆM G4n5ErErPd .'@׉]'tpa !XT#xc3,`3f ׀sEj&ǀ:ƢrFu .&F1x1wt;PNMNdT>姚3?۷ᄙ07n 6nSnP z k4FIM66j{5K֤wl2Q`40+*j% ,R@rRdڅK:pl2l24Ce~7{'&{U5*@*(h~ BGR:=o9y{*NauEStL~\$sd':qOIv?gp9~/ 2,#Tz5aLvF'z%+)싈w)r(x&i0zK.Țwq/ ?t^cQFxӪ-Ob))g\t_|,$^3F ˗K*aؑ´Q"a4C b9Fbt+v;Bs݉ݹF[h!%M%eMG2H&Ӹ#|о\sr}9־E,,k_'nM{{^T4wb}vCN:m$:}. NVθtQ\":ف^-2<,@w`-L`\Q4=Ap m")D%Xp=$ 3 g@vhE¸ 5lq2TXI)AuU[- etIHDRsq&4[$k 3>?δv`NdHqb> So>zH.70H,p8|k<<-g#g%UUgt&V+xPDACLHD> :fW|plm>L,'^cM8}?}3v?p>҄qn$$짚omy)i0ÿyIs:ٟ-a$9q{ rcD sB܇s;k ~xufkf6H7>l(\g>ok1e^bwsOr_uB܇K/zx-ωヤ?|B6>_t齃?{{2r?OЫVҁ \mz3/WwwS0Ck?7|/ͱs_ޓ ؕw)7 )X9?s֧!\[OA&^{2X@Nː4!\@\9/0}&VUKo+5+6Cz~1KOMߠߡM1 )3O}//_O(PK/SBCԭD2rebar/ebin/rebar_core.beam|XYtUVֵ\ ΞJJ)`%qѬ;,Ke[, Iš%Mkٚ!4M7Y202 /3Üy桟{VVW{߿t@`ۮ=7iT~G 8\sslRsSN$W>-kJa[yGZ-FRM:S>R9B8KZtFJ3NͩrɖOLX+f#Vu+45r)|NsB=2ey8q~uhD8-8j1lf hi)Vw:׈KNs F:֐ˣtژUJ+FTbyu"W;:E<=RePwZժc (RqAZ eTmo)b)g&&Gs\mթ*غWQQ^(>Zpg՚;|b\WnWx=(aE0ih~R,;3U\>?ϳ|^ʕJ36/Z C;m"=F\0D"ux5F'*GcMS8颗\MGN!*S=qswaXՎuF]Br+?ekJ V4'~N-| R;d!RnxW.6+?-IEE)b/RlDv=V%~T1?)+"@pV,6y}aszYhBOEQ!hN\(6ϕ=VŠ3AÂ5qN`@`h-xtWoZojf4%KI#.f ۙF?ӭFM>LҊ6 CMC FЕ!S̒AC~AwXm2ȢAw,dh_j(`C{>p,נ_ZnDvM 5$6$8B=)ч9L/ZD&2y0}YɴD ̈-Q`oAN\{5E5Ҷ 3V Q{jH![㙔d2sp#U~*\kȳ7tu/5~*7|ƯW}X 0pMr`D&9C}lDm D7OtoHdxc|Pu7֦0#32;&HZ9*#OlVJ&U++h!7Ui{^ Aq~o-Kc kV 4íQ 6FńK}  `D ,3jv` !LNM81fb3]' ʩhSZB'a;WPu`Uo4~XwG¸6Qn!탴X$p>/|=@25CazTHuq3 yv;!{W];ypwwA}7\^NnGq^1Zun%w}yWp.M׸{pp7&:/`-ǵ/MI Yo0Ta|P6Wud31jg]~2 y0-!P4xrv#Jq=f@Y,(8O(8Os9@p Nz*.$Q_΄4=jLp{ljD5ߣz4^ƠXR3/ k u͚o!hTL8" 1d> JLG!ssZ5{9>N p[lq/*#h0TP qRc5q4%LaNt ɵ5>?mWg$PPP*E,QDffZ<O4 *_5AwqйIES>7ZߊQhL=1bPPtcv5=sxNp84Ýu`u,,mvYb[1S<"=-3$ORTzX̏gbdD0cQ`0OM aAJPBBF'p ˰!k&3{34 M I(Czt~!ޓ`qP˟p;lH$Lx%dx 4FV'j[R}.' Sl) ~d/j~f&$zQ [j/CwLME̟NœR9@hoeSЂ?& ߾.Wo+^xK7l8Wlosrü5q]^`Ԏro]qIwd߻^%7ՏnMX ǐޜ>ߣS ȗSVS~;*BN,Yp;~ z~BϏ 10~^o<Ћn} _.0S b_wGqQĴ?cwK,8T\1JF~BG|6_换E; !/~21?'H#~ro)~F?z|,ߠԟ\9BﷸC=p?Ij¾&# 7TCrE@2heV X0F $Ɔ I% 0AVH@>EyV\Z _m}vZADA7VV >k}&vl}=s$&fuV &h`XB ZdY_Ajal ar,njQ Z.F;}n*KYV)s԰N",Tד\5YUpM K0$6L'ف,OTFߤEZ԰Z^5Jlr0$Q3ET8 l(N9*Pi1;+#<ß6H3"l:ΚsUJsns"sIuVڳpy3j+]j[\*/RY)p==Մk2 <ÏFd6@쒉 ]c5bU[ SsI'Xq|_$!8c0EWԑQ3OUejg%z5t^Up?Ch_^5Ё2]s??пD: 4Κic@U+. )/C=X-K&6\ClcHL9zJ)^ZKZ,J=C|m#3]WBv׊pztJQ1tf|`((N]\ڍo$o$*r%fB*(xf3az#88*Iu;q/Oa` d }׋bWHg#'6e1 柨킨zY?x%]i!Ϊ ȘN8鰧B9OI-`E@N B$†#ڹdV8 ȣj ܨ'Jv8"? #-@ q{@C_\O9\e|{2)+\B@B9xro>>_j(OW =d/RSC,PNc KPNUHʉAee/8?VfBY.ra8: RVog-dye|"6 I4&6ʧ4dR;4ʉ=K'WNZLY-s'>22se>Gy13_Nbj_Ƹ΄ռBC/R*˻Zf70>D}dze|1{|W('5I+N:]IO>N<;:P봯CTkgO\vi`JSᆢ90@FU`evɥV$f{W}>{x aj+fN2W\sgo{j^2LLynˮcǞc)/Ώꦫ2/nEQK,4*)Vo oYQ?'ڪVXBt{޼ޙ#NOZZwخ.+J[ki_5KL1jޖw \r|Ȥ;gnWeMNh3pF׆vU]urSd{zi?EOXgze'OôzGB^Km}|Gm,W7V XQk6<'@vw@~Y>wlKM_l>g멽ڏ~.-,{K( XD?,3@  h^r҃w}J9oG\AKDo)WR>:%CgPN~7&ӽ+d}%=_?$,D/nf01 -|5OQ6 &)}͞3wcHDH)ӳlS=`hR=RM r֑S`Oe28tLl ΰZ &Ci.c2Iyl1á>[GA5^A(aQ(ң0,(CohzMF( MGvbB4 Fs\4-B AemCSAߠ}:jTQ3:ZEt]C7ѯ:Xn}0A/8Gh<G8ox'`+)8g8<\gw<b</ċbkǛfmx;ƕxލ}x?5Í ?O%7%NRIޒUI=^˒N@)H Bp)BK1YJ#QR,b%>OSa#=Q82A5s0PK/SB1<rebar/ebin/rebar_ct.beammY |UtLSHLC۴ NiJ@y?QrBW[W Pd%X)Qq#bT J@ I( DE!W$HI'+KXА?"D7Ga4!+c>#w(*bpp hB7QDBUt ?hXDTrC 9RD͌C$:j~g4(\}bdj;q6AK4Gƒ*"*P`*h/:=^35QfB(::u'&Q yE UBxB%RWSћ9Ā?*E =$A;T:1f `,*:!D A@qy(e{CQ:)k :v䌆EOT`zP {=@@c_ 6jQz_i Mb4KI[hnTXxD!܎`٢ICn]$) *) z\Pc@ N\ z\;#|aq~ZXo͟ z$(\@mZ~|` `̼?V%Jwt[N_vy]_Fk񪿬_1PG:x2:O&IH\36UpB1+92gR/YR@Bj'JXe!!%e2.88a%v!:;S%9G`m g=JVGӅDtؑN`dHy` FLѱİdRf`:mɫs7g[~7٦@RM9&Aޫ>S:Ybg޲4[ etu3Cr$ˇRtrդ7q\o Tc8H&ծqYIʧqP`#M63010V: X҅Gi80jDh 2b;őV?Xh$LNF mh̍\8a86` X !$JOd+Yzb:Ai@)82tUs62JŐYH D(Ǜ XDi1~h"qHf8 C 0dӓ k1YL֘ %;Ijet;uv&t{i2Ѐҳ䵆22p,tՂ29/ Fpܓe4qNI8Tg BV cSe4xPlWu,d4,i8TU f)!z2`J X͑ 1Z{2sq 8]Yƙ@xfF`?SFfw|\iTw$H ?W$,0g*ddXdYڄ&ʄP .G!Xfj*YE*@V!+ #(tL!:J1* Te+A؄uXA8 $yz¼l*p8j6X!HЮv.-jR^*4c'H.T8,coLo U *q[q%xj K+1cf%9ģMlBخTVD&Va~l8gdJY%@=?-@aEEE`ʁɋoUI[h)4ȑaFFmce9֡wd >JpyϕQ;u5Cd#FeJW⪬UY>JW+W)Q'$.Չ8P%LdJ &2ZC 0T:PuAre@֒F¹fbW.R0Vke Cլu2Z.pkw N,WRk©5FipT/j v-F3 r+wUұ꽄Wc5FHɃ5C0ف4A2rBHڅ ᵫNWn> Zd^>DY`lYe?DTeZ D9(]!2W`h-]5]_X`\",ד%49KC3Fq4RoӃpS[#w3[o7`w~VFحKd"rp#-i/;Uּ oE$M2 @æk'S9HrHt/$>u$P Fd1h6 l4S@j6@ٛlrX3Ar5 酚0K4צ) e 5}v\q< q1դ6kXotgB[â5/NɎy]?a_ZYaj:1hSXKn {*xy7jֿR jOž/&9%=fyOu9v?N)m{ˎCKz3_ڵp{䛛s?~Q=9?ο%A1u"ܧbo]IL5ە "_[8  A3Z_Tx ~*#\LVxoJJ(5GUQT'ZL-VQ^Jz(K>*L6R7P[M05BIKGԃ精.j7u?4 ,z#"u:HLSަޥF}B>ާ>>N}A}I]E}O}E]~P?yqxM| g ~*?73Y<["/ z;&~>ʷ|'_/WSPwQwSIBPK/SBy@X"%d<rebar/ebin/rebar_deps.beamtXt&tä(@.MvEi2M#iO/xǃ#(^sy]{OڔٳZߵw]&Ï<;9pz`ÇHX$X5b_W~aszV&KE9VsecT)t %QuuN ELіb:+wKfsZ.zRjVFGZ | 92үӵRVLm̯Qmj~6a˯sbG_/TS~D\~j=,jB)b!ou֯73B5 + ~VgU2Y5rmݍ]Gӹc\/H(cRnUbݴgbA7C%7UKRE cJ`?>Q>)bkNx^Hp83uijEPs~^ ȭz=wv&Wl [  :b3ZjuzR ^,5A&h(w/T]*mtk)1['^wLf5QUS2=kGЅ=~ihC9EsXlu,*f Qi'25cвOal4|V"R &r\]Chʣit0P&=ߙZniWO>ڝrS[/VZ]{R3O=VP9'KVC.$B9T[X'*2׶/-IU0)ujn؍S]jU\X.K v -,٥-*ݭ:nMeQC"m?/DpݫѳU):,'۰^["SZt8b|F݈^ d|}zM';|6mw8fBXIo CD]Fiڑ-V s`>j`0S %$U&am3bۂ_ ?h sصX3<]Xzii8k෎XuY#=}, )~w.#`f_Ҫ{Fu>`q(\kk7#fz`~Ma[=VO~P0 zMU@ص/-}-+N8Fj}{#rS]x5]c& oNڨ9FȢ7% ='z%zJmD)H1kĎ]C-Y H&Sck(~!z F.:XpG4_5]A-"֊Qf$`wDmNX/u`9[/þIo Kp.O0l$ u݉ho7/XآC6[&C7#2E7:@x I087A&Ā֨:-{S][^~* ~c١o͋vvj}ۘ -dvKm0P(^)E$'ۉD6W#w͑ݥm֭݊nJZ .CSK$m6@-?=7[Wwva}{;]g,џ( Ҡ'nd BM̶t9<|ٿ%6 Kw걝.i_b[=<s|Wl qWce=K ^o+ c}H=t X,\o>H 84ߢy]*x%v rY.ᠬC k{Cl^aIev>. "t6W4Ϣx\,؃q-kȰ EMfh 0LvC<<۔.Zp0u6( P^Țt}<SLv[^ʵYN8`Ep8#>~ĊIyG4b/v2(|G쨢ˏG{El^Ɔ>潬 ^ʏ: ~*{ OIr{r d͆Oa7̶v>ՒݵyuB\h ! 7(F {<겵`pM"O.鋮I$ճ~:NӠ*)Q֐f"9M{|^$*z? 8ѧx;au,ywl'֋i >d]w O"N'晀=FVV@1ryNcc!O)4m\/81J ɖ:&IjCUAHZtRb{̊YEJ"< i|f Ԙ; =.TXeT~;*_2$*$de "~rx2||F=qG98q!X S@-SuUWj+pUP%e@X4 jtdM/_O(ϫKGАwyM߯: njXb5WX#k}W#`(؜s{Nq:b3yPٷ KaKȢҼ³Px2y0&*5#ag[g요i40T՚ C4Bt6|_X;D|1Ky4n .6w+Wd7zi˝.{lԿ,bq|aJAxwt @eW+^꽯bk8 .-?_#ZLoku>"Dܠz餩( |CI9vlT BqS;2"} ~_GB = b$Ӆ!1?ȇ7C)chP>Bu<) XФ8ޥv/Q/!O7bO759J#ۊդzfI}I:*_<9bAu$6 3ؾ9 +=E-etfdhtpgM/" %Xd<ΒKJaZܝwm!0G-Q|BJ9(I޾;K'H&޻d mPIzJk{C<~` ]?-pQ^us(}{Q?8Zϣg^>nOVs.Q1|Z>- hj_t@i6x!-"#Л;ttS>5ED[tD w+Q7@DΉ/lZX_G\oOO&8W!@ͲOm݌ͯQ=|2! }9]')A%nYjA`Z{ z^6t\ .#CYؔ6x ,vqChaM5h/0hN`R3^o}bD<U;58@/%t:JpE A :`zͿvwZum=+gW&&ïycݎ}Z(w(wz eA]xnd;f-}ײ fS9~#V4vcG4!VnMhS|Nkxw#>H<$mx|R?+dtACCұ͠mX%^-GJGt{ _V:._҈-n7D1G 'Г2Sf?QГR[A&K-*)W+~%S[6V_[}P-FG}Fx>e/ɼ)&PyHo>>mDOS{xu9a#*usQPkj&ߗG _[RF|02.^_Wj/ŝ~Ng =NV1TXn+e_ZVnou7^~}ong?[VYe[k|!}ήoϮnf}tpKvuW\e=X\8Ɂ w*Gq Į HQԟƮ-Fhb4أb7*vP-DFonrO|g߽k潁Yיfow13 wElmffofGgEbpLT•F/_u09ɍJD^FlPwR2e8ͫ}JE3ޖiEJRTAW w bFY Nzc4Ov0?ynKiN^3x)=৳VI1x,F (>E?C˛MvZx&k4O1-53@FARe+u5ZR\EwF1;J1Gx1JVF뢣Mpbr21t#NŨgZm1*SF1l@MvV`";ƝSdr)渁2MpNŷNAR,$ŜTq9(:Z1"TcOڂ'[O)uJ'pV{rpo+vr?um> 풮])g4;Nz+;Ӿ\IK1gL)P*Hzrh'RشM9J0XUgZ2@[0w<&|!M|O"As}aiߞݷ;PطWڷ_%.@\43 AtZZmUӐrlf`$.ePPPPp*R+(Aefs2Qi2W]`I̜ðx~:~?k!*Gϲ ̜swqrW5ܟ0h?`3s^uYNL: A.HmbX(-^$/ax,_ZЊGNXk3s" { NQ:_/R0*)U zkf*@;`G[T%6 GWAVnӚAɰ ,a4.cpܾ ,t P4 3S `vj)CیъPt[s #jKi͌O J%-H(SB;jUaZgC`O7MJ0iTK=\ ]'834v'Zhc0Q,8k ,ސ'kwҺ-E/47+sL 1F8xi q ;n "Q6wB2xԸulkZ{0)\`f&8fQQp4z)v'mffYQs R\(4d-ZdZ!@*u(R-WG2Zm0x4PjP<ezZBk$}( [k{5o}JL8x p)*P,]p{ c獪Hc,GG:ІRk^ ,  A`5fb )H/hq$:3s/SzHtH pЩ O ?1+6@@49!dC0.VFD.0D5jF0Xg «Z<{|c+ZbІ @!c|VNV o :H|AXO %[ .{>'уu"!Vq؇ZŞN8Vq>(*1Vzg_B؇Vr?ϊog h~ GڳqmMtP }އ@޲jGmeSO q6&r{ g3k+|JrJ/#7k)ΐ%)"Cb?iNξN>\Y-aUb]bkQ.G2kڥ숧`Nϸz۬(92O[/^zu}ǩuOn3lTc#>7{~ mr.AG)~Uӡx6bΞҦǛU=OZS~$y@ϘQ eFq6c3 =~=j뾱zߊ1OtO |~uw2z]q&LZS`qɣ1ar/oШ- .) ژ{ܐfzL[ڡwV_EWda76VUh^MZ!(M髯PyL o<]}&o|wg}{1cqfӆ]˙ҴU"ZQOj{do%^śBt٪t+HiosuEAiGj{x=;϶h3=`D.ܕuhtAvZ'7߲c*Ֆ\hzqxc ?6f ynYS^45ˋ%ciiSmg}z2ƍs>fzJ5XP6hąr.ow\h\hcew|qfثcetXE gz'|f=g=;ZAf{dTpdRn>ynקa877VB%fg%%|9w:qDBfۧJ~Բx75sh.E*$=n1ھE-؈Wv=9CzqtCQyNݸMĝ;.pn4FlݨR!;4ӳVO=bojC<~%c;lƦ G߾v?}"zP,|TnUVxg_X_9({zJ?vƼb]EkM11sN6'( <kދ-|u!ξp8ai ?Tt30S[ѲYSW8+mOI{e^Ky 9kZ|Q>xӇ,ڐf?>vv /W?^hoɊ՛v?ٝyC{W<߿ݔW&`| ]uP_~KZhoie[q˲x(8uX>xhJ woÖ*F IIm?/}iےm:Oߺ >ýz)~Ť~֧g}z6[~֧gϐwgO%<' }EfqDh4K"3P!c."C@B5@D"ې|t# Gtbc 13H$z;$Ʉ:OxQD8P;"7%r6 "Pc9~9/=T719W3y I#-?yYY۵e{5L wed.,x9 Ov2.-7wx`xA~jznL6(=KL]zvʰԴT[68=;-u( k2Ex16b`%2S0HӶ l&P_bMŮQ_f܇竂BNn CiS/Z=mxiy{Vo2y~zVشLKf&%;Z^)C=`c@jȴaɣr%HԴzG(DJ_=G/c=A%t h/:bCb1@l.=EJۈmv"}EA(vH1F.b]L{Ib%&b8DLjcőbX(N'Sĩ,kq8G};v>d{ql7/PK/SBD7f "rebar/ebin/rebar_dia_compiler.beamuVlWw9vs~4ikA;79qu+KM6טsώϜi76uZӐB!P1 BUih&1 6⇥>}cIGƇl/ЁhV6_Ҳ9\-%x4#-fwFتW9C*eudԚzVr>s/U &?UͲl+M*kve+ŦUϙ4v-8+gV ".6_p"+'gIUe-ܣ̼^+R2.ZFPJJfUͨBo )50"YzS4[ϻJFfAW{HUˬ .hF]ꕼ^(UȔf42MMf"1[ֻzBҫ{=Q!-5>`q/ҭp6PiE bh дrMS)(P*Q8Q}KhWi:<;WCNF J| /Ge M;Ӿu|MGdZv_4n"WE%"*QA9?ܚʭU5SCeLcQgI 4e^d`gUP2` p *S_ G5A&2^ N=';R=aaLbj( ɆmtP۠1`*8 tPwL#=M0:e[u\c0 ƣkD0÷myGdgZ=; ;c7%/;۽Y ï2%7g7r逨Wwnb Z|wx⤼//4-5>V4w8 ?F/nՍ[g{o,͵Dn]{_ÿ^~mï.|a|GGo\lM8]W {‘nN嵫٫?jɁTo`L=KϹ/V rGTߡ$xTgfw&C k[Gͬ[9}%S5ؘk z"chO&הD%uyLf| D?IJ IC#RZ:!J'J҄4)eIHfKEqRV7PK/SB! .h rebar/ebin/rebar_edoc.beamuVlWw:9&MrCqݔd}q6ڴh9%ܝӎ, iDvӐ@K?X%4Р/MTT@i|V}}>ӻщC #Clc!BHZ^1sj0AΨֆQ)%\5BVs5[/[51/*eKcmzhk F XeغQa qf窊=NkO7ꊆ9؍ת9*q_K:഼^ɩ+*vL3]G9nVe=*+3Tk*_ZQhLUQV~{4U-_+W4MrV*ޣjUWS/Jq4wECpƼfڱz˨5,mkvN3JHCuyo_wVNt9w2 C°H@k?lHD 8H,z(/FRؑ2"8F:DX*᐀$ hxP$B,d\&ɒXePT>ǧɹ]+#,Hh$p<,=p!M "@S"%Q|Z@5"hT™ Df9T%_p_̒ygy^bVp0 n#>dd\/lB97h`ֹ@U "sӹ8.*1@SDw8\8 ,AKh K .B\$ .: 80 axA$}az?J@ : wŔxҜ/zv@ cMyjFu޺/Fz/heKa5[.@'a_ދلp:}&zyo_\Oo=}n'/|ị/|xO$ W޳];xC;&w6|oq^H{.!BZgZvKwތ̙}kxorƩ?%؏|3\~9?d&W|^ǫW?juR'M[W"G/Ư=O.V--7*0 ۗ{{xo߶yzguhȶMN*}*VT4O;y}oÞff*Et,tעD@E!4 3ga*3j6x+e}J\S5=;1̩* ؗ;82DR%vRuwtpnl|tbt[IUSN$Sݥ3dS:xET@Oriuy(R*aKuóhg ʼ֛-+Y [6m.齗LO/!~8S??Ÿ?/3|}"-$PK/SBI+#rebar/ebin/rebar_erlc_compiler.beamYkpUVeՉQDڑHW s {BOUϾp4ޙ/۹J=,DRpuwZw.M;kG;˥F魣zi`LZk6X pA^Il8+OAjP}RDZ/U&vFYu]6kU\F\-z &9fWSu[Zy4o+DWu  kx=Eztīz:W.{-o2JMPZGV:zZֳ_/Z rMg|iwMV SeJ0w5X)j.4ZVrQcid\TT*r]1[*mNՐc 8VB[bTDFewrR@LBgnZoz$5bGsP(mvҫF>Wu2_sT`vʣҤ\Sv> "ESr!4r1zV/U) !]wzP͕G1[n7*Y҅e6r>]G٘DS5r"[yi^&gj]B^\6 oJ5+[ys}4dM~aTn0';1ۢu;Pk\KV/UrSUhg}2[: ]9ε7 |gƊ|Iaob}p;יk#$B :f9_M>DZO ~P":V ś FbEAQbb#Ʊ)`cc<¯:5LOw6]ME.90M9Wps-[EK/΍)D uowA#װ0:VX? N|R$;ai}jPF-ew!a }Pa(԰8}p4ϖ158*!a4`McJ,4q2L]"SG`!rgh1H:lEw5Qt4[Dl"ol 5Bhaa[-@ED[GE;׃dI/**DŽ-I m#n_ ?-~OM@ߊ<1uKkiZuCaKEfUɖKЗ=}WoG_.B_У@_/턾[wW}u;;}5}ö}fZ| 2Y"m|VZ<|w*,3:*Bam_È 0nFFU.AIDE60+S [|ډ>z_aZJI+`1CP㩑58kB0x7^~n0:69lOېU](|mv؝4i),B ,K* %VäUls :$QYdK՝h2,*DAEVP,gr8]ALJ] UT!bLL"d#\Ĵ#~gF{;P4==|vZGИ׏!Ikw2yj*swa9!v!#_1 d; :%phAo@ H3>ӷFnaݜN5;]τRaA>O'ß@'{L'(d6 Thfc$3*p3I]Bn*yݗo.t~gHªq߄v^yf麟 l/଒~u˖-^V ڃھt83+Bۆu,&O[|Ҥv0 *zV&T3fa x@V{v7p}aG(یM\Y,{f[4@1z$?=cYdctK":Jꃴ#Db=I-EmTCo :h!~;^tԃ05~8Ve>v;gM4n'Yms:Ř80*#/<yqXި@-oT j/NI(֙VKSk$IVG۰XOc5cMa=氓:>#FeQ J2܂'('͔{\ɏbHy:>]Cc)AmJЬun%()jZQWXNLQi.sPb./ ЛB`C zN80) ?bcVa7Ժ|~+,w4'0h$i@~D4S| ;@4|r߯& _RIg3N/0p?a(^t|ב4roiVCQLӐso.[9ᰳBM|Vؔ^s9у,e,,~rSȃ {J7})0_A'as $i |7 {ƝÏrd;^ X9=ȧUpAW]h;Wi~8Rsk@A??gUe1,PLĴqOjG@AJd|DFo$2&v\j`! DChXWtQ^^]W r^/( 93|7"quV7N3fAѭ亂}}ݨ>mJ|CUݏִ^d팛/:u*!> g(,[ ٘ HZ/HDl`)#v3/&e,˻.Y}^/+,Y骫pu_\׵/j7zֵT 컀xgnځZ-c5!.bxnZ#A_D u$yNZ| L\{r篑FY}'HzL?30ed$ݝl&V z5߾ˏi-Q]q&{'; g{ ? AgvwBxaGTĒ"ܙK' hޅ1 a#36Kf g8#jtO?]Ԫ?"~d %s>ԧ}0}nZbBG)[lq|//(<Xs=`OiH> >q? >u/?89w5}U~] Lh$Gg m6"(/gKCԣ[TI_bms} Qr؛8$HԷ evEoI__I[WAU~\+pPad} ^uޝZ0f n՚ZsDbAVf⃍>sGpיl)o%_"P~^ 7}/1yTa1s3U/Ӭn0ˏ(|]ՍW.k;zGcxp-n/ZֆƵ>ky84iµug]07&pRgo|'}VyTWXJH+p)R,\P#1.!$D2*EH*مV,PZ[#XlG#ֵu);}}0{ ((L(L))|(VRs zPΎ 0D}r!jG z(|9M/@nAř=Ff󏦘\9OXXǼ1OG/@gh7ଳ~}*s$?įRrSv29udzMؓ)푉spVIc< 迌c.Sסށ)z8_`zob^ԋ_¼ze߇A0G8qa>9>89f (KkhxrH!f^t#y 2ْl,E9+5Ul{{7:W}P尕g1}3 8o-u>Fmf$;O3' 'MI, }Ke@) .s;"^|'MSg4}д2o] <1wt_7I02o/ueUtq? C D'y2c嬉EV;w۹vΠL,ϷЉN͎.cv•ղ?hk[fn̻HεQa]NYrj|75S>mgwgjpӪIK}<!Zmɞrca[mQffLcmn"! XV3"? Gc^N}+8+8jډLmLs)7/^>?:m:ӦŎ%~ glrn;Lo@͔u7^2%%i5꼞e# +",Gm;nmU}'18r>us?BՏrKD힦VN=/eo0(uYE^0|z>=CN 'Q!WQl8읔:{lE=dzG8{g*؂?X?fԗPM=( gu98gR8cvc-,SꖋZnXC cQ=(-[_t<5җ["P ƬT$S)5`*ḁjJ*b6`&Idj9c,)Y@&gLexD*aV)n)X#DL\&\! w7gϋMfKVGYLwsZ;xF{EIpBm,y.K=Y Ռd i #d: 6ۊCҪr5LCJRx6W4Jvը߲:>:"ZHK.)nQsL _Pf$0""&D"&H($Nv]SRHI)9IjH-|K5NNnKH? 2H0!<&Oo%y0L`25؃G`.L|`>|K bAqDH-lTHtȂ ȁ!B'JC%j&hp : . O)1'˜ѣ4Ƣ@8Bp'XM'RSA`j" Cx4E뤶=HT0D'SHXF`&Y4 'BT"[M%™mD&282ttZʤ!2=I9Tc Z)Լ'x"$iT"c#/8ƃfMOFI-l 'fpR-?Ģc $PA\"| G ֕S%?״pz֘Hz!LPja.>/k)-Ǵ&m,%c 4CnYiSZ\bkNu] fJ<2<hT0hyx$[;ٗnQvB[\.[4HiL, %yxD:3i( 㱠kqKz"_OLjt an"Wnb89hp})Yq!z"z9I^=8  ȗ d]uKmQD7 Ke2+.邺g|zd Xh)Yy"\!*0+èoVFDۥVrFu8a4B*Ec*>BQbC]DZ1 IKĽWIPEΘ٤Rh\QT-NfcVe 8ɋ IVx4l{<9jV9)ʢpɸ=f\E2{@D^,*Tl_fO Erk_ڶS[ \(-$,8˪_$W`BWlWd.Td]dr27P!X B[:yUTUfhV8j޹qB~Ig!J{ ,8I>x8\bU&q+rNBdjʝ@vʝNZ򮎮 9̤;<9uWuqn 瘔5'RN p G!墚n 4/*{ n^d&,K88  DDX$[@;e&@AzPͨ*"jv扨`uo$iSR]Ԃ\+dFd'Y ABɭs2a)ݮlr-f]I:+I@u,,ϖꑌ2)`f̢9JEM҅hLF  d5$ʨaqg {47xBjm 8!Kj5/ZcV$)'25G"eE+xn6]nJ8fځLeC#pʶV2dj0PGV2M_mIP mՑ tJϨF':@' B`>p٥r/"'Tz-BT +f034t)B?I~Zh☯}nhzd>X֑ gcрq̏Va4&lVC8:%'c~W;>M2ۘ0Ȣ!0@, 4a|!6_I ^t k%ٗ%BZOETg1D nmIo[ nnHiҭ:ASaR2ߵA4xe6h#TmV|E(CoXO$̖AX!ro<tMȰ0l0P>~OZ`9wP:Yϧb򽙣I,]EyrVЙ4R~7 Oκ5hm0Vo\kw߻;cl?=Gئn~gYR}hp_}ɨw㗞Yt:~otxuk3?Vꅕ7~ $~/j7~8a_$l;}?~Omxފ:tgXx%^ΟϴzOCS l]|?~mo ?S[ڝ[5&..;xCgW{ߞ:[8P^K{v*IW/='V= m7$~?_/W9| ǯM=>57|?u1OYոچoƿf|?i ;p ͔2 PK/SB U rebar/ebin/rebar_escripter.beamuWkp][*^{Ub;cc),{evY?d$$.<2y-zJJCC( 4HHS\(6RMJPeh@$-e=wNDg={w箴[3P齲7I17 VڄG\LOd͚Rh!H0jJ+*SO4&|eg-cdbLih2SDRK&&Z:Wеh<23%D:rn:Hۼ^ts"[55h+lr!Rz AX&lt2| M2gLZUPf"V8ckQʒŒ)llK:]DBrC]IjT&Ē(˲ ƶsԎۮ%rQ6`BSS9NDxCf]y]JKMQd&O:+ޙHc'3vL Cf ؏t^Oh9\I.LK(Mi%4f( *-X i}ɘFw)@bt4T 9M], ,s?4aJV`?׀DV0[eJ!%&T@3ڇC .*ne]1F+oԌSM4W)Ee*SQ "c]Rw+Chd~-| ‰ )n3NإĢJ.͐22 ϙ[Ĺ*e!rhsK}n&s!YqBU]Ƃ]+@:bVqD"D6w$iC]~Q+|=+D\61D "1‰9]Π+]:K {OQPۆ"r(+:p]>ev\*h#_ϊ| 8;2.,Aw{a-~c%#0uh^A qf #br8s^itl؅rA2p-ݮQK("[8$!lj_ z@ i^^@ 0s^RxNj,TR_bux-6 ,^n:SO"J0:4NR/%a;ZDZ"zj4tNK%zqԊX=7z{i[ꭥP ]Wu4H2-gp`@nQ87=n2,CM,^eF0h7MP)Dc{ \[&pBaE~BqX"!0|2Yvrp* _Gs,)"4̪X67p@ωg\{cߠZ/dAI#UP6CP2& jB|= ]d^WܨcPt?68am0mD_f6PvT㕴6Zw@H7^>-H#Ob_L"7G'3s/>chhsB S-eqrHF60q i7תT",,J2H LװݠM{'߁6aI/n9nhL0bM` !zpGoi6ua82EZ,A=0n^ *jE6<|ܵxEb{``Ca! 4'wðT&yaziPpaiD@WQ6•X q@6R KZfˁ*;*-<]nU@hڮ@k,ڢY.]o᩼.02|.,ݒ/ոTogQEn+,JQr+좳0TkaO?@E=Pm Ѣ~Zco͉<{:\͍ʮZ"SNM{z?nd#oܟj;g?muz&tSվUxkn'~u=oɣܽ>?=U/?`ѻipqߋ_z)5Jf#/ҶN@1PKՕSmRfLAi3LsX [e$bX*7ktD.Of.ǘK뗞'H3VI:H7QH/#$B&l!#d\Koq8"dd'E{Ƚ>r?9D$y!qy;+Hrebar/ebin/rebar_eunit.beamX[sUV[ֶ이J\H:E-;$J08 c5r[j"- !\n=95UT;/睟@Mռ9ڻ}I^kwSCȱOk5j[$nϝuۮWZQ8SlԚ[hԫsNwCvRn^h^[NP6fBi~kM+6J.atZZkF\ë9h:u]bQVJ}ͻfgQVfՊcsUr]4].]utVUi;S/wd2tR\ jzpEsm7Zls=o5QgᵺݺBb;5W{Q qW4;[CXbxC@!&]N$K)L]r8J9Nh*rgqlXc>$}P5O 8 MEN,[tZ=L2\4X#oMkH7*'vd;~M#л:es֕M0?qYDՆSrK\4޹vHT uKѹFT(m 4=wh߬-4{\w=@8.K2lIxj4e`lw+R{ه&pT(T/^r5yĠ:D,[19ԗeRV"zcY ys+~W^r*u->t=ec\K(z]5JkW]&& +$\rKN}N(IDE e_*a=uQ~ ^vc%&hYoܙ]bKNRp m[J&L뼇͇ Jx޲NY r:|:r: -*E7•[I ԥψ+3dtιNrfUØ#|~7mH D~ζ 6kxg]VV^~M,\`.9a׈ir]ܦǏER){aj ) oSRluy!6适Y>hܲ |TT %0,5|ӎed4HjW+yNWH0t[awMfZJڔ00j^KL kJ3Bpr ˫\~Ըad2~wGjמHOb5%fNG(¾_W~M}B74-SVum ӛ@SFzcBoR⏠H b}mհ5W 3[BM,3[JT6AIOpf=9>7/;laܯi",J" .nm17O{'a#jV}Lи3`m ¾L ]*{{҇4!3#͓ꍀiY"SZSte2giF@ 1mꎲjϐ Liyi}nGM#A#Jl#>l#IvIvP9`+,ݣH||jwgVG ,`X{Fa5+`/%zt$d"$$ы#<.!%PqLռvղ`GF0&4C6LٚAk$Cp椊l @77"~$IǞOFRIu>,[8znUx~: /(1]AT1#Xn 1tlN,[IJh%9,òͅ^-\$WGl]DO(1TG1{RR̓(]Jn?C)!RC9>5JK7FDBN,TبPW?!<<? 3}hG1&Qiؖu)`O2G(|Pl ܱ Nz1OcovaJJS,~ ЏN {lvT̴tٶI4q,BSj'vLmQ|Re2``I>iIZ~ߎO4Vxa'ٓ&K*l'b-ɐAįa)sjmyh/n <m`~9/2w{Nt}""ed(g{+}`B%p5>4ymV㪎?ahBB-R|qxln)(֢(VZslч7}_F PʥV'eO"f? Hukh07' xI>y5j?pw~ڟlu MlObg˥8zjޛ_$i7ѯz}sd_R%dK –$>G4~Ui4O ISuRvɯlJyhD_co7+/+m:Xy3+ZH(oլnFHtwa;*w*A[ʮKu5[P׉5&X=RKJW+Ro-;,@u8{XXAKgҖ((Q(_,HFuvP;\^~%vA) Xԉ<mHSIy*#B( OlX xEӞIofɄI&F2dG $! W[`JĠx 8 hS@)7" {fb~yVWUVuu/D$s8ѠcEZKϥ)˳D]&QRv(HHO?3l{ EΠ ] cm cc:qtZR!#rpR0Or/.b-G)H(sٮ( Ͱ>,fG/ %̿.tWX@x|HfEEÎAʴ0+ ~U@w Am_9i}0~mi2?\)e} ZHlcPΥDvI$etu2Aa RYkcՏU/"!X%Јӄ5a 5Ċc ~f kyt-*Kwn `k)]]}b,jɺ N{{`P-e-e{H@z2lgt'>$I[df$2,2NK4FVrγ\: 9𭔁!WHBeK"QOF"~Fm<%Y]hד,oN=Ňlf\ֱcUAƒR1NfU/3wAߏa ]3Ks*=iS({OZűovf84asXg`o16WȶvxYdv ϼ'l]M!l鶚$(l[M4 ({1>a(ZlumSˑI{I.0t˝= =gQ=DŽsWKxݽ [;I>vʪ < za|4GT]@%*)VvKopy$s뀞H Hy%csL#<= O,JHѠ (#~h"W{*kqy#%-q4/aOϳ&aǷ`2SO.0udZC &<\W,?|%v] ˄?yz:e^BepE*(L*O:lV_U(WBqo z &]*3!6m:X.]:t47Fuw F@yM{SOȐO2I=7u'< 1Ŀ)2dn[f<Py G*Ca0U [=<Ѕdɘ.Қ.F2o5[pamκI_ī07;a.xCWxM"XPJԿ0 j&:.JL@VR'G4k+TSR#`,w@sbۉUrJVaXmZ0̷Wf2+^oNi)JBPM$8kha0l~be {-i +T%X`EdV,7ﲷ iBR In?{Q3D ⫸ 5$4ѐ"{|tmfZӈ_}9'JfT`q60xvP:Ltw`PN>_fT8uI:{/*u~}]g(<탹٘ %~Z]=Il ᓊ40L jC{/<Ȇ ̟(6fcaOtܔθh+.\'Ӱ%& =1ȅ!ī6 g$\h@DpC%t'Iz]*1G\<$X&fRy%ESrO^Y75 QjI/ `ثzC 3d3^IԦ ]g"Mm|DAA'm k!@C0 ]'O%{|~j3~^yPS[P[ˍVBQ-Ey5 TK.2r4x3j 5#[߭S# u8=N,`U=b߮Á| jK*lf|,4ae\!~N5/CxĠ{B'M}! 4PPY边"dDQj2HS2G 6P. P#qk[7H1Fٶ*r{Kʺ/v/`ǁ#W9;ف9šCc>߲1ޱuØa &1gδ-g1r9ۡ=cery\ep㗶|9WGq*k؁_q+u}*p6;jos*{1?ipW[%Xn1챬q:F4X{=g`$xUUyjpeM ࢎ O-n۩x򳶼g-.eOx*Z|B-g\:prCgۭo_!kYfue85m*wr򝶜 ßu6_,56_TWrYaxS1.٧|gZ:y{"iTU3&w,cz4\eOqܡK\;Hk/pw8e3ZRCwmc͏{6)j;û!֑OU-D|{P߮us6.} "eYwoϛp}ؓ%EMkh抡Ӌty '.zwS3VVi5~ExtF΀춦ꁥPĐ#ivjkώ4%۲z1֏Ӽ^6m?y);j<_^3~71 ?aMZ9i}ܤ;ʒŽ@gaQ aw쟗qj'ψ[$x{K\͵ͺ?ɉgLϜqGkK>ϛֵǶ|?|fGV]rK?*)ZukPKڝ|m}[:]j7vΚ.R޳YvG{չM_?3;6SӇyM<,Q-{>huM~E<^ws/Pe o3SSq+GJMgrG{Dq3}m]NqMS.5_V7p+x/'G̚tlϚAVjֳ_cx@ u?ӿ< eF {YvpGn~n~o$l3r<Щd'^O]7z%oO&7[WM>y?mo-p'y{uvѵ3KۜXHyw2T6}O[<éS'KEYP໽?PwSl 6xy-+8j­hÝ\sb Q8g/KYzdsw]=[cGFJ}kN95~%vꚤY0CS;oјf_>Tơٻ)}x myPu_~$"^ hf(!7ⲻ»:wIjj7D:N5j$eㅒ&#: _1|}~lYHÃҏߥ74|QvۑC*O5]^S5X闯^ykhGɁ߆.Qw{ߥndJgQ ThafVcߘv|V rgR>c7Q>e7P>!\ɵ>{C(gSgϠǞFHPeK'hOɞ@y=)>Q^eNY!%@ʋ})/~zSgAy{Qa[?.~I\!p{>e<.}'QYg"ufzM_Em6;Ͳ#\olH(;/ ޏ7.'ĥbE rVAULKLNFYlDb-*RTFԊ8-ΈQ'⺸#_ozCA a1 #a4H4HLȂ\P&f, sa,RX+ Zۡ*a jZ8\: p=hSxM*D;c'ݱ'¾0C0 #1 1q0wq(8 Y9PE( -hEсӰKp&y8B\Kp)rW*\kpnX{^:-lsl،-ZdUvɞ#]䮲W'܋ c x hDxdLLA8{C Cv,`8a@lȁEܔ:ePK/SBq~Q  rebar/ebin/rebar_file_utils.beam}W pӝ_8dvrl',d˶d'+,K'[,')m&餐f\m%С2 Pvf(mV)fVn߾oohCQrWoLrLvL`4WL,.RjԔLRt},fy3&x$R#Ŋ%L.)9[Ka8TBx,IP&$6bMi6 f0TBtF%ؙd,a;HDhN$B}XjRQJF E,*)DRIdp.F<9ŀ&jfj VŢp2`2`$**KL28Kp֖eaa 0Nrb#: bg-u\kQ#X `%]%c`mXC#w453XG<9l$JɅGNbNn7i#)W?}?xQ`$"WNA)g!6C;7/Lõ`L3;ǹgi~6;rms^ৣ"W5²V{g{:r|vy[!6aP`Ox>x=9n[  PC`U? KSWߪ9: F @3Sk5Qw鏴^& ?D#"X%]?n =PgrLC{3=vB]6(#;:5 ,puVFyTA(*i `zOOlQ kY9Ǚvd@C]-6p_BrjaW[&FWh+`>nq;zINa< ʠ&r?,qǶWHACs#4OCk͢$4y/XF%/T\ .V)xǁ,@h b1px#y2lȻQi^062cLޱ+ M [ďh` q; ՆOb΂q>.o0$/W۰'z74X-wpH]m=Ƙ@\JrCO<ԗM7|]q7|ӦWju~ !yo2۱?ru{'W.zy fEy#\5'1c?{gGgo{#| <5ܾ7;|7=ks⭙SGصϋsWmNΉoб;Hz:?ge{+79F#V*,^䱗xˣ˯w=wGv~{~Sr?D=7|k(vXA\?0p_~QKɿn-/.>۔:v.5 :D}7xOէ&FiI:æ3Qݍq6E(@:$x州9wt'0YboN2d"M_tvnAq2ϫYUh,e%lDP8(XBL30P}%MYjmj zڼ^oS]=b(R4{]Spdmzha͎zZft5 g"oCtl&6LOB2CšPi!H'jX4,tGBpM8}^ ~?w s$~ ?FUPK/SBQ"tR"rebar/ebin/rebar_lfe_compiler.beamuU}lewk{׭|9.lqk{ʖ [V6V6Qwmomnh̀M0f D `C@p8La 1%F&D}yޏ{q,)˭f`2#b*'9ɤ奌 I.SFD!1N&l˳a&(*) QsɴQQJ1r.ҙRb HH 7B$Q QSd>)`¢$9)r(q" VALFe%b"oDVҌp #Jy~L Qȸ: SQJ 6t"YYrW!B̄P6RTZ߁( Pm!L:,QQ @X!l }ϊ!z-NW'!8 u0WGR֊ zlLshS,,#":xj-unlG]̟S{N;cӇk{fFO؉bv~_YovO&>]0W&B 5OUkDqgKL7iqHT}]z˺ТokWn~o ^vrfk%爛GTEm;g2kn5~Pylܠn[يQ;M, צxOl=KO~Ss߸&x+-y7I_M]ziy2ZoIP剟c+/Lw# {`-fY`ΤSq Ё{[?8`wFB-~! }Μ&x  PFIi&0R`\4 r,墼qXXugk)W=n={AdkolJ/nAgw{챦HcmGX۟+}2(8.d>ōa8T0eLSGFT.got $mH+xpF}'f[x-^|5_ x;ޅwݸT7PK/SBwrebar/ebin/rebar_log.beameUMhGѬ]8۩rl$$8zVڕjW]^K5C( 4B/!BIK 7&5tcy͛v߾G(dup9Mp!4!FEsKSL[q`?\uY Tfq5e aݨtBkX$p/ÀjYfULǎ2aYޟr15jõ4 NMuu fzi7syt,cZQ3ޱaY86 YstPx0%_ %HX$J8_ᐘ2%#qDU䫜$&;2餺u|?o`VHXz,aJ>)>)>iw}J|)A$z_UٯQ_A3J$?TUJTN2 B'9Uoȥ7DY%H^%fe:I.(GQJXט~I$MUTPG$߂y[>?#1/ pJ|= cd& dUl^)+?鿄cib"c>忂8FhN!-0TOcqPLc0:6'+b*˲NQWPf934&Qyuc= K+NC, ĴtCbcn(lz>'DJ~.<|  C[r.r˯k塇G)v?o}BƒϾCG,ɖSeip /a{8Ƃ0|lvHGdm&N.liӫC|ڦ]cb]Q.4 "NM8b,v膎 ˴ }ͭk{7hhQ͟WWWJ KKKoE[o7hŅ:k>~i~qz_x};՝um@᥅ yL ̵sϽO]="ٓ=Mm \ Е!YOJ9&錢Ғ ]L3RP6ŊW ɆeJϩtZQ%uaMҙTZ4JIMNP#Y ڴe3i4(LNqa91=ӓ6'vI-mM'GKUM3VG]tOF([Lg"yHMsJѰ11f' /UP\*^b SKȐ8M1P͙46vi㬪()c&k3!6##8JȮ-ueX5YeĠ 6TeSJ%2fIJ̬ݐ{s_s tŭ+ٌTe(DMa]#7drҤ5JQNKƬ5$n AOHH.#jP᜚mN$3rPG1Ȧ.c0ue+Q \^х (:3 d HY[/,%М"Q$iFI CYoo"Nր[ $!RH痨⥸`HQLr)ZYw@J6@_/E0(kr ֔6Gn\~mڳJɬ d H< 4+1edDI `=jr@/œ=v3rqDŽ2naXb*mHE-&qς8B$Y"~ \|ez|XX + NbEx.9L̵3Qi1PA*lјOj~'8̓v.MAyn$&0WbjiΗc1up#* (LQ`滉INb>W$?9NF=g^>vip k,"y goit)NMOS)䖠62зXB7݆P4!cӤY35[LXhb x][t"v-˓&XL+U`a6( $/e8dj=coؑ`]@ \7E@ֹ"Bl#y4tPk未p/hr|AñcE@dN6@$tSăhUtx6qQv1+)xVSM2Ah$AN6 & Q~??SFF %lZ "PCq~x6 4jƦUS %<Q6G~A=_h/{81u3:,& 6XZcko" Or,b7 Aγuws@悐 5 }-Hщs59 boiuvu@-X9 g6K |+yYv6Վ 1qG Exی{aׂ1w9~ΚpzqhiKoNAsg1w:Nl&G`ͻvN}INܵqݜۃ]ټjGߖ=q=n}Գs_əϖWCJx rxljwC}'x8lz؛?ޖ1}=e X?+gc ׾yɳG?[u՜Wѧ>֯[ռ~of_@O=ɇNj?|hʧ]?:辏\g&֝W{xu4Mk}orgLk2h;Csi[j=On:D`|]G>}K[?vkJogk_Iպf;K{.]|oy/^}ȃRGo? r>\sx#%ޥƓYz j~-ȟ¾:V0=κD*v[ѱs Νo.p{s,#}?f͜n ֌RP#nHMm;5x@-.:6OmOc{wd`;E%a&&d} 6w 2VLRJ@9KiUIRJu}+k.b("h41b.]&ѷw8Q56pKE fu%D#KړC/WpP{Ϙ }}(,i am'!(\,Web9`ב̍m plMցվz-p# ~s?oE-AK2ԉz  AC*D @ґLC[еz=4m&t#!݂nGSh'څv_t-'j?\_PK/SBSx[ \rebar/ebin/rebar_otp_app.beamuWp^rٰw{!$@\.w^rQw#kepQVQVCmiG(JQƎ:m V{3߾o&o=˻uuaJ2 kJRO=3Yezqfz&[pd KAKقbӵQϪrڜ=ڴNsWT5Dvo+*eJ eⵊȪ)9kq^SLA/k0"I*ųQei%JSnT:%TKP$ ڈ;)P(S[[)B)5ݢaecAW5e,e3)YϨfB1v깘 gNdhR:QH3CC|NQfr@G[JM+HNyY_wdGsie(S䔉ZF:-JvS7()L43nvUK($)*&uMNCJJ2/M*HV D) MY MI;.v$$VܗLNyOEٔ` Q74hXoЁ4!]."AG c_H!JTA$EkHv s'd AO⑸wjH"Ab:rrRLj=8^4]:r]*")d]3i;(nH0)b^N$q3$6?iI.m#Q5րy$=4Qf+qVbDŽ 9!ƍ BP8A.Id oK9 CicpID %ix|bIJ"6]5[rP>)ni] 9]"9hgmoU*}s nqȻ\~Wh \W%KiIq pRE5O _%#P6"AбqjM@B!f@w}sIX<`6sCgـ8&1d G4PbaQz}| nZcAqG<(9P64By0J}3 >-, B/x<\\G}isphA3dAwB n)"Z .g? 6m H@հ}Krh1` @j[ɷA;Ƿecmʭ$&anpI\\!Y,ZToi9 ղ B(,rK7'ڊAUfV+́~l\Ei PbB:n# GGX<T'-TBP_ZDi {8[kiHF6 jba-RA΃TXӚ Ri5 ,ٖI9^2b?,0h A| Z4ȔZɼÚzMt:dN,ǚ'kKM})Heweӭєrw;nuW.B֩w#_Q~_ç~=o7g\sN@Ϙo\u5wkCu_sJ}m<Ϫ//uS>_qеWo&R驪&7\o>$5>[ލwn|7}7z|7[p]Ӗ\yqч٧'ا2鋣1w;峏+ȇK I*|s7M{o>7y=wqOxϑB\>ڟSޏ0~_/U:~ oc9kC/PK/SBz7.#rebar/ebin/rebar_port_compiler.beamdY{tՙhZ cIFyGRɵeyxbQ"[B !^!( }۲4-nҖm9{tߝ>gF㾫m bדZ f eg8S,lq/8?DS4xlq|$?uYN #zPUj%g`.^G;8), 5F$0aF(9?o%պrqlߘ$F8?-Ll VȬB74Hhfѝmbm -,Z Pd r2d4v7$j̏vcptlfk\l2ga6rtYBL~Ix4Ry b q_,}bȫyY`D- Xš\Bh akeşݏEaD!~mdi=6t%Z`B'liX@BY\@-4h0C.31p~wrl:]EH:.3_a|0jlrB!TxBB,cO{%5TDX˒8u 8qY9pxJ@ [?i&2tWUf! "'PT 5B=.@Pdp˶pfFܩ˰ؼoSS!rCKx Vxڐ4Y7.  rfL k#g|RqV ^CEeJVQlu tMMjzZMY(C5bz)`uK@-_F DqIp9틗) /iQPWJ:e+dbk%oH#}vȎͶjaE*oltvlë:fiuj\SݢΖ!o[ 5Xa]oL \v-\':6sɷ m0d uH"eu\-*yx$H=MR0w4,^vNl=Zc@0,#jh3Mp#KCIM ]4UM%2߄P}.chC+R݂l j{ eb[Wt+Nův}ߐN d:Pߏwfm !w@o r#H8 <$%~\RoUMI~s;[94E7cY(MM`1 ]L;!T{GEMut@#ruФM_Pv1-3.M9d;xu*c B/ULO*FA-" +x|DoMJ{@9A#jd-mM@ 9V4u`:'3;# Lhe`x'vwMP[6z/wY`E[B6[}PV$8dN t|04ԓ 4J$?\J"ʟ2X] AV%=2$ gIDjP(u| 8 +H?GFO(ę x,ɏi^Le)zQWر?Js%yG\jO! O$O`J LIS>)"0% < O)"kS \LaO&j,,,gWaZϗ\ [8Aze~y^y}=;_xq*^[b}"R6%R%fOxXYa/y {VW~eyRUwzUBj寢oJ> Nt86 Վ[ãl BXho=E퓸_?ܓԏjm/U5M.Ox}mTD&) 2W2?QZ^Yn6ۨzKPZW &_Jʹ߽v|wf"]Uɷnoy ! Ѥt }[Eۨ7\ vc$?%B3l[{yJx. ׫ÚN%do#X~NWMoZOS:)-v hlSM!cwۄ{g@ Pߗl&;zO%;M_jq1¾#l^B"i\]y-R6R?(W.{R?𼋃[adG*%dmVBC/{,W2eEjQ&^OOߦ#sp٤~AQ$9 OB>ޯE1ˎQ` ^=,qh?$-|(3h 8BAY?)Q{_Pz >J_^1c}^=<<`ǞA?RدD_qc0į vqiո9!C yOy:Aq$"WZO?E`B ڙO!3)3=QѺ|5Ij+`a%F0IrY/O4aVM=E SY纚t}x_ kysx=OwOet`Zzk⡴ٗN$/w`yf|&ā ߏ8/w?Ih)\Gkt|搃Dmubm^O,9ҝw>ל^lHckNW4_^Vcߏg}S~lƢt'hpWBn&8`<_{3 .B޾8V4?} bRUw?.+7nSg 0#xfQ p \ B<|%xQ2p.ʇYbƭ5gxB>mx_}{<I!!`V)Yn1e 3%*RR)kuAHB".T/{<<`&a80a_=P VEw@ g5* A} <ދ<އ? tC"4EmO 5Xq|G@('>(NxrF#Q[:^ O$ԟ$G )COt~_v5o k Q*4][=Gȹ`v cG)]4JQnO u"fLsUsݪ-_"޿z_`cHl(?KEɡDc.t^㋢ 78u[|jeU>=5MvurPIWTWYS77ڜ[BxSֽc6ۇ}q7">IW;v01;ZڶC!u1IHI&?yazVeه;m,N^J~2]jg,_+?Zh_0)cC9Zi+SWi:D,X3__6{8O>ec96Tl738ők—9yw1֪E{ CCz?yiűGz7TtıDFlم? 7lCy QzM荨MhKG |^ Ύ*h,%^4WqW`$D|9K&NOʄ|1 ΧGU*,`G3B)Qyt__s*_!O~Q/ fq9AD@[<Ϡ:/0qCY<6&bq8 o7B8,G-1sXxҨ?Z1i}='PI|'ʎ)duxLmF c/oh-H62Tz(H:uDL4_~]iAuP=Btx3 dpX~L+(xmy뗂}f3!Y l\ \P΀+Ԁjpԁ[ w=pG/z@5xK ނ04s` `bP@PrP*U;zCM uԇn6h-%T@[i @ C:?0F(`&Lٰ, XË|`섏a/| _7pN)8 g{*DKK˩T9UK%S pA \:c PA|A 8@< /PK/SB3 )rebar/ebin/rebar_protobuffs_compiler.beamV}lwu|/B.AĘzI0nh+|lsvR(P;~T?Ӧiec++KjւnjM*mҮ[]KL,>ls]\!!ͫh>2sd2өBe1SL d*$A[0妸b~F5'jV\8 0Gc|OlOGN.M 5=)HhjU!lq\B5?0Oۼl\6K8ь^%OьǢ0O&[hdMRJ,[&VY* hdJM0 {D'xxHnXtt hViUI(-7֔LiXQKEYQfsЃJH;tڴ^ћ#>ܩA'{zz;4V_LN g` |-pJ$6#L&?N "ܫRYaRSȒ3 5L6UML`K$upȾ])Gʁ@ķ,C{#ûwBu㩢=p+z@|s,yg_`s^/@SQWLeԉѺ=ߣ)_Go":zq~eqwtXH7a3>|3w`~ߋ qQ q<',᣸g>)|?O؏oyPK/SBv <rebar/ebin/rebar_qc.beamuXkpֽ׬%%vKKW8k;l؎She=ֶlYW+@BZ-mY#@2-ΤZ0!4@p 0=wT{9od,0eޮ]Zfa,3 3T%U#q Kf3BTjjrђxQB&Ql8f Ud)+8N(ɴ3 Wҹg4$(RUͨ x ;˨P˾5%jttAei1eRb4QJsFH8٨6HDDPp0~}3*gx3ԡh*m`VQ JZ"3L,r )j*Vj䴵@MB4xJ 8[S_Fs:!A pj9.>T ^+HhoM>W>h_qVgK=Qgj'J}$+|f}e`)o1?:JVNdA9lqaEVN_e j +1&r\Q)y'R171xS;/[f HDN_!$*7H$)zdY?$+=.%N0 W-'Diigz/ {AGk*[kN K"{IG.,JDQ\t@\)sne8L\.K$=^z$0Y(H"x6,rsr0^~=g,bJ]oIJ&Lcݜ g(5&E| ~EdfDJ9 * XQGUHâ(#6ՂBo[ U׺j2ג"B B$"PlkfjHHx` ƒX6e Z+1Q-<.ґhxz#h7xbyȬV +#RmG#r8mɷr1ylqsclym\Hd+`{6 vv @Ɯ6B|`xV&/*7u H@7ncV@Lۑ ˒ eQ*@H}}#IJI~{ɵ7&H68AAh|&!AMBfM|k\].&&Cʼ| Ic؛@MtكrGnCnR̢ G?26(8bQ yBkV $-n׌9͐R+#S!4n!3$ِ(r$K`+ <vxQxwJ|whWt0q/:j_ Nj m<.z|"G5uMA0#B00{A_Gi ?!AXwjAv~r\N;L&esr̸'? YٝX@0);@Tw Tp+z=foZFv bX(!O3H I/:YMk0Y=HΐtRl?ɧd ۩ET_!}4y Rk(7cz0 t[zR>?Hݏ0$:dyʂOT c=97LydczOCj7x{n۫LxWwn47u񕧶r}_ڼx_>-so:^:'>4p]˶c^8z1x-&hOm}GYy^sSyoIǮ=wG|h{k}E-=:+/x:g]~!uɽ"/Go{ܻءϚ_lO}ce?]641l'{t^Wg&~:͋CB{}QX]T'=A[Czd P~'v:n_G|ȳcC y)4ƭGRde֒`\ژb6W?ng = {J6xMf9`K0!(5xg䵑yƖLSyxse.rH0={{+@PjijZCP]3g*gh| Cxk,%zd(E[-sFK癢Pc{cY5x-A2oEѲhCkո2lOП.)Tx/ԸnN+Ha ?N1?3Xގ7b?pq7܆n,<8Wku8s8U7x߂[Q|߉w{1|>')~?g9#|5|PK/SB<#X rebar/ebin/rebar_rel_utils.beamuX{pӞ] '@8|{U}:&ͬ:c9uEd @{RtUZꅂ#3rOU)dMqژ|Y=4W412WȻ' VYgrZSٓ))gMU)ySvF;&c62e, mcJ%! lQ/ْJ#pǹk\gkTkC$=-: أEё`H(Gn:c )(\ZX}T8hC|V? # PzZ}Kx4]_#?fy>{%?{ "Y_.JBԄ,ECT{>QF㟡ϐ@@@J4KN騟=P# H;Qe.ޠ"_.%d=!4V>Xy}EK>D?M8 ⨞r[Q);$2\9DRҎPA$_䊃6(ǁFNOPnIqw;Ƌ!J;4Z<鸸BB6s.1T60ڸ.XE |yyX傃6'r^V]-oX: y.$5.vQGQ+@'|}0l>c X!F퀏1领-wڸl45Ul.:+Pm#HOH$([#G?QZ.$j۸_(䧣(LdQM {>OP ԴOFBb_EvxzCEZ6^QOqsb7WӲEAn8 yMH\ gBb/qlqo]G-*I4i! z׃Һq X+Rqq@}R,Qkl7ˍe]~iTŪ:$pu1q nUW`w.Na}6^N꟨kˡ5Vv6^p .&. @8ѴחFN@gϹ^zj%Ǫ5k0OxVo'( dBV&dzDEFoRГT͍i@F|IlH\tF(G >}xHҔ!EbFPlaq$V~'G&oZ ⑸ oFIcBM6p*5`SMdB*kkx38YJi1<]7 ~x a 2 @L09@s5 b&ciV6nZt(?TQ]@Qw%PEuzƙ:c*katBƧf_1>lL>gNP5ŠV&\ ̾lـ"ȯoC}[i]Ҫ}r#C~/=x/K~O\v[]Z~;͋<xZW|ַfwu<}'Gwቝ'wyr7w~\󕶿rEt_O-p>qSO,=7M~u_ں+G^?~H_C7yrU͚Ym'Y6y7 o\;mx$5"Q{,źfɭcÛ6Oq's+ kpDcLxmL[Nr玅 ܴa`7|Fr(9Ņ;o*agcvZNnY.e:o0w 9%lmx? N!]$Jb $YKdLF6r+l'wq2A&&MJB! 9LG#6y#O',9A' E 9CΑ[yK#K2|L.IPK/SBLi }J:Lucq%:IW* w%bO KH\ '&Fh,-PdhHݓJ\*!%5IsO(DX;g#J/t00GQu^F~u3`J*(L0g:Y`GOr!L,("D$U˒p8L[Ĕt6Ed(d-٤4B8"L2~P  c᮸)$O%vp3/ pŹDTJO(%Pųڔ Ţp@Kp*s`'"&#ftN J";)KGfJ^dRJDZ2'}g2OIaB"E Q4}TT!-(F*Ld9vu frH "#S}gZzi *Q+nbh$E QIf ̎GEly N2T"J肴R DCu$2{F딫N9m@{Q$[ 0L̢y-1xFO/#K!-=lwR 3bx-0EH竬$gP7PX YxNUm To JDQ  "(Y҇YT',K܎F\5SaL쮫@pMO %&Xgy[{'^bfx%[ŘO8+z<zbVFVeR=$q&IeNkS(Adž+n^-w*dfͬ:tTuBOgUuuRXUc5!㞐a@t[| sjlUOA +G^Pk&96/r&\ek|=]1͍%T <!?J aVYlF=7nZ*!/G֧U =uRdqo%kttޥX8ήṀI~vNkG|(17"Vڮ13s4YT!I50kUm\ph Ijb#ܚG ~lȷt&O_NrB,n7MM~.3nao!ٺWl'l1bP f;_>nb[~uiBn2A6P*.bb1 gĵD;vڕG@'iu%lFvkTw֒I:PrFNy&w#Qñ]`'&( Dq sbeWaݫnx. ץJZ&" {U >m: tmxaQzGQ}.w䝍TlS03%A9S!{Y:z:X o^*9R(*^FV%tHNBa"^`bMŹ#rPf_mEQХmOnoG:T_+#>lq7oZx!xLCD_raxB'rJeɉHjK9Х&&S@eJ[ Fy]&vUZ.2" ί& 5bCg[PqHt~_&TPtQ|zTe ײ )p(Ad0RЖU^ uH(Wy5v-!<4=F;(;xX;81GJ _w% p٦]A?} J`h;a0BJ.Ďd+= Wc=h Eq{ Uv;O?+Tv8܏Ni8 p78֑~3cPm%;~k][ިRChYFa·ة8`n45wMyU a]-dk@cҧ}в>!{w :_bSnx ĴnVXV#k  0ptz| zXr79vjM:d9l1 rp \iPxӯ-E}VԇPԃ&vH; uP#B4A/}:E{怉 G(厌_qč(v%|:n:o$݆S,.Ǝ.lG;[p:aϏakK[v29DNy r>x d藌ӍYew`c;^-*#q\{6AiOYp MAƸd,xlٌ ɐO0dff_s@s >t g޸_Zh-3dh\i@ՆTc}kA+ :C7kx|s2CN{$Kq]ԒK${o4c>rEx3Ǎ=G֑>7Ʋɣ.:~>^ᡳ\:ܚ^rpSg"ww^wo}-K8U-ϿP5poצx-t?l7cſљ~cりql׹5rƧ-~w{BO}2+O}m賦+f?t{~宝+ξG]1{*~t"ka]z鶟,t U-{.۾̯^ 7,,|tꖽsʦ);VC~w~:#L3g^\7i|SZ^?Y/>]'u诟~pH]x7[2r:Ǿ/fzr7/^~o}띅}%|)zx|h?VO ?=-s=إgvt#ߟaqW,7K*=ѷ};{3QQq{olsG /2cGY;ҹ>dkV=}ߙ_9vaq態7-c.{ɭ|g&k{6>ƑgwN. ?/+rex=Rw;G/Ҵsm:R3.zW_{q㽕=tāOn٘P}F~Qn QORPM4@ Zo3!`h4t6Ƌ1=Q@^c\n4MM3YꍋGsz 0^"DO4~ɸ3?ۿߚ@6-$oI' 1,QN~{ er %sh,ǙX8Xg%"\TrW1r֦C}ܔZwǽvEfb;-[=]J+5oeoEdeWt6CڼfE~t>[嫪!9Wz/Ea[xYإI[V=A~~Τ#_ɾJIqR5ve6G`9Н/MHᯃ{ 3$y|m-(v%a.UNvN> bT&uAx?"Tz*/^It`^ <*I~\U ,_5JXʧx4'% YސWG딒<p(40H({)C06jdN hcMpWӣ^ni!X 6p8;i.h.BAm1m>D3,E eZގjv"gY酫K}Κ,<_.vpkB\3w.q娂y;;@qP jWZWΨ_ׯA;)bQHJt$eHeen]u4ׅi$49QE&i+=$;L;FVZgM`: t@Z,Zep^UY(L1&D˝4 M1fٺy."(2kL&.+ykI,ָd%V*mQlڤn5v40YS0m"Wp9^YwYe~Y Bv;C;k Yp!%9ҵèa`4sm3ZTx 0ٷɳ껝֭wze.st!a3qugo\O5~O+:Δn.9t){klI|Go~="wI7nf>r/z:t ߽>t>8hn}eg~\[O|}u曷vC9\JN̉zlfbwօkJn|s\Ww{/{?7?A>~>ћϝ\ptkN"Q'Dw~zos?[}k43b{(|vҿƮ>f_ݻy%Fqm{ G漽Z+%s]nWyN5Eϕύ=Azԃ6A4QAh+ڂ6PP8ʢ G# PK/SBZო~rebar/ebin/rebar_shell.beammTMlE~c7iK[A^;&iuҴ6sR@Zwf׻Y({/9 8p$.zRčg boޛ7߼7ofܮV K,lqϻaE~,"b9" -?Fsqh-1# >.$1¦GXh0znl:(ٚBQ` Q.||7&ehr:L7y}+؝fϘiH' % SR/q9W[ AK|o ; r&} 8mK`q ]IksPk{MEi'?G]KJuѵC!3g3ܡzK1x}ɯR /QRPOM Sv_Mp%FL~J1A!)xE>˟r3$GA2;)Gx9/w_;lB6?_`%AqvuBhNf\h]9iuyꃟg3*aP`-;ٝsgdA|}; @}Oں(>~y+!{*F1A֡$ إpr+S"s!q fɁ)qH)-|o#L}Xs=9 'n@&vZk7Nk}Ń^j fu^^ /6[77=VRQ:_/^_{?N;cՅq4wrrD ߣt wbK 8 W  ׀upG ` %FCi1ȣH#8 QGQ0c=߇G@ ^}? 0ΓY?&4#mB a4@72 'CYwaFVR(%,;2UTl'#$*C*;@qhĨ ExL$Mn > Vnh,޸# &x?{Iz\i n'a$<=d73~g.yxv`G=޺ѷ3k9kH^\NwOfglrc?WN?S~l׿In:G }|k_!qn7G=D‘Ks-;1yYiK5Ǖ:[ڛ76g'8nϴJ3p2h)G8YJ&Xx"MEә t^DDc,i{_R[b(ߔ/LiDlD RPoLKkX(o fh<#p&/fSZ-rό kSaN**0s%éh2dvWc&X$6:hLg'PH4=c6·j->BxhXѸ5 f"3MfEyn$bZx UDԂ̰Z$BhrJ6j';4%<Ղ`a~f0#fnd0 iAK,_gF@< nZK*? 2.SU]̏ Ϊ󥕟(ŕWXikdVk5Q]gp~:a,&p,MkCS ZMdǵ"WT%suV@U|U{tVTdsS؊ZTg*T%?+gUV[.4*tw=u #*U8Oӓs*?e*t.BE!e>n+ʟ*4 n[mqs-n.v TizSvY9J G__ܥtq.9]q9(vcTqӴB[ HBQX~V(Ry";a@DziS_SįH*56|D&j̓BB~*B1#* T8sERIiiOjSh`LIQG_1Ӎ)]F?t?S'3`i,͚n*Dt2XGiPV҇lkM$Ŗ[>Чn_R! *i@eT#dYj 1j=I4rrRK.̳sc,.`/\يDvMhwTq(U< %Fc ʵw3w.*w |OREe,uUT4OpKT“yԱp/E.2R10b,( JX袁נyp fՉ..Æ(06*]f/1~+BLv \fBs PԖSE")IZVU'Kf-+ې…Ja!;aiH[D@HiZM.j C}^R9ɓE"س:Yfq+a~aѯ*t*̸ʮ^=U HƒQ ӯy1-q]%2EƊ15v)KX.WNSQH9E:€;9H-!ۡDDxаT'+!t'tRdŗ*e]&EػBLL U Ćuo&ͱ!j@&͓hNa{M qeprVd5DWI>KzU܇*nP/ aY(M_"yQpkT! Qq瓪YU#Vs:Γ:i]J3RcTǓZaEe CZTu]z`s S<Վ6w_ן?XC1{6pv:i&i4HMN>]YsHldQp**=ecNؑkڔOZ|EVvk&lc2#xҾBj=:Yͺ> E$l`Ҁ".ʻu{m_c&U AI%oIg<Ҟ ٔcQ PqD$;KnX3 E[( )z ]f>{ T~N:5TpJSOz1/>/-km}]4m) Ԗz:SmRı]sP>i'JiB*drP'74ݗ wcBAr) VpIIvѮ2ڊbF݈ =y@'=L)}@a-Dj@q!vPm4dAT"&m^k(PFL\a\+XLNP)~0= x?i+ ~p$OuȈ~J4 B0G'èw^u*g([x8[샬d"93쀾tiеN: ,{O{T`9 ;GA]u!S K4ϚE$LN:^}{zT=- Ǯ%nJῸB[pD'.{`Ȅ%Oٝs8Pyk^II qdT)z&v%Qd?f\'YĠ~t ~LU-Web`u]_^\O3ǡ8=a.rDdQXKnޥVZWKLW@ѭDcfE&0LO;Q}GIKDf\ې " ueR쇢I \:q!]~߫-+kekG^=o9/vlun[;XK_8vMvv|񎺢μZ0{|uƮWVDz9gݏ_.<#h+_0s?VWo~ zݿc~qK\tΦY-r+;]ΖϽs;oc7|}o}UJwW?>T MYV޳1,{^s/kg\{'5׫3G?y]~yvO?8;fGZZ9?uSvOzզWF~ѷn~oWL=~;ӷF͔N?(/;N?SДUw|E_~oʒ^x7/ozw?C9'w=GgtqvG.=]vn2ǿ``ޥ/}XYlr݈'|&cӞxx]wbYyܹghWqu~M/l/SsO 'o*ٸQ!؅MzwnqGo|X{ΕN,O_{^~Ǧ>o8heXܖ_,ޞlmHw2ά+wܽo#>}HAa}h+gSvZ:&vk<`88-FWVY5X+6;V{ ->vX:g5g2){EE8a$7:q ?f{ʯ>Kuk =d߉l$Kn0FC~"DSCFlqh<F7w@\$9Z^}VzV֬ V| &rckWpmǚMCܜhFY^SLi^_ee7R{{Sw-n^2h@g*}-/fcb&: 2* - U~TXWmMC*Ѫ:c*cU:Z*6˾!/#bWMƂ=(qB}&uE1otyJ!dL.R ^JY"EOTQM-̈́iN%FAb`)%< ɰJ56f]#93ιKn^xw>o~W9ʓG*T%T/jPP!բVKQhN+jQKZֺ45"4~<W\A:i&BY؞v# cƺPK/SB  rebar/ebin/rebar_upgrade.beammX tיyֽc<2~a3dceKla,[8@-Kc[,zؤj]6lMBؔi4KC '{h`!mCڤIJJw9iit;3Esukӝ*bݡp0áD2ŤHo\Vbo@i0㟖~*-x,OfV G'hD %Cb chrxPefV4$Ƥݡ1Ww&LIDA}Bh$@2'&%& {v MHI`>RI% &O%[y0!8#E8Hᄴl&LivόR/hOElv/@2ߋHSzPMsCw@CQTndwq2UP%脼 zr7-M)CsfE3/"zNq,A]svNticY--UUd) ܐ _e8v5pq򂞋Y g7c 8^gnZ'1xG9*gL Yye 5P`=WYhY1E]w&o.J]Wzn?dۙe}O#WKF&=w}nTIV`sXFP RaÌJ,2*Ґ-i"gl!2* g,GHÛH (z#荋,˾ -TP w ;oU%sܐV(::͢x#] I-DNL>Tc]@¯BZ,@D@j -QJBM2"ED2$tC:T+~-od`fIw^{-<]F%fe xnfdTM%evCA_l1dXNk*WȖ3y-#Sk aiYhFӮ^xid++[BP/$ %!TFujAXn˓=ylznvx= P v؞?둀L}xRM6-0Al9gg]CV.3HRWf+""q0ӥUq ING+e h됐k] = HyEV6ac/} VwW=f : ^xeOA d9ìnimS0P-x۫[3$~(m#ZK?Xnʥ8ʙ1>FiH؜?zfb@uQ104>;0t0 4\w 5IYH(Ѱ(/ \W20+U0O|h| UZd\+:mMbc䄯Xˮ8`4j1+æ)Cެٯ.Ɲ!o_@֌X6dhrwfw|ھ7þ/æ=IN4O ØJEs{6wžnMߣuDJ,3ol.U[9>UPfӽ?ZYP^9ȩ7Nl{. +ywG N+{=q>K-sӥ8y}ޡ}Nx'}k׎7|K7 -oUwo>幗|ƖÎUTznxZ{6e|c j5xDaj/wHIUu-v,Ds>hs?v}kCT9t={̛z NM_|ߡ]/~gcO_:'"%'mxg/o>双A/G86^|fo~KIÇ/+x]=?_a^gZλ>̳ݲ4|3?ݙfze}+]8wTwWxT{_^YO#ϰϞOyw`+C/|SCɷ>{o?o<{/[ݝ?>/Ծя_q- 7GNfe[&CmڻNomNv4hZKΣ J=U'q ɬ EJDG}VӭTvm':z"[3^%CHAU6H{AN4 #"D MSP$N S4HIt elNSvE+%~_ï7/e&W?5:?{}'T᧦PK/SB. IåT+rebar/ebin/rebar_utils.beamXeJuo PPC@}Mʡ}t:ݕNKCQQ^/AGww`gwv[g9a?aOu%i@w>o[T\slOv qEDQfܑl-3K^ܞ|dXr*E/ƚjV(7gX\ 66fKˈgUjܬ綸R\|wZ,3!/J>Z)Mʕ=ϯ\䖡^`nKi溶e-{F&_^2=;iax}?Vᮗ~j$Wɻp ?;B_Ύz9'[j&7v`eHVǂ&Zs' f ‡" hO\-7V~͹ɜʭX\R*b!^GŜ!=Rs[9w57uB2-N.ݼNu v3pH7[CH>bSG{<\F3F @sB#65+mylɏЏR(_m5{%׭2TRREx >*"wʼZcHLȝbDDs!T)vˍs w痸QA^AP*{0X\'󨴦\=H^*rvEݗ;PÙq!*'[LKJ5Y( T'rŭ4Y#nvZx)6&QQp(#hVLw|f*ׯD5FūLrnkщnT}Yˍ[[ XCB e~;BnbaoҨΚ.7Yn+hf`)bym_2̉٨):KP`D a6}q*ދ ];Ӗ?vkzgQX:dAyI1}6{JY$ڼ޳/D:p~`Ms3~՚fnTuݱ<0:rBFG ;sL rE߸ Ob'VB5ԹTQ6@6լ Ͱ{֚ ak:ҺJSt:w`a-"EDy[[DEyHۨ=-pP 0ժ8<JUSΟ*vKgB?d5jX`*tCTkoхW˩jYG:NE=n(coEAYȓ qɓ4ԯA S'OOaHdwkTf K13e!T_S(~ST3Wt^e7@ i~d7A7&tfKn&`}4#$-@@_o›64Az;[ɔ[|ߢi6ЋzY%t$m>~&ҬCX28ۍ.6\y3AV,pA?fl _kxG9r%߆ID3]@lmxX}"i qib +6.F9= S슋Z9+m3aʸV>)twL"ޅ.YHd($YwjN $wrЌd {gB-Y Up֫[i))HM|B:^WAva=|B&Uy' gl0|ld5X-T'>xs?߇)ki-V<dl_l3i$Z??jab;d[ג?0^`%Ie(4r8`*2csP4۳"F#:=0`fg/ş.Tx=@RvD߅>MDi\:~B#i-礃vh?C O?(U#ڀfbDxfDtMFG@LaCPwXL0Ivhz)HOEf;1 È3wt]AԨA(nR 8USQ{'L$Cx sxrqs XV"h9PFeOŲj9Ĵ{=B1##IAX1&߂m?Ҝ!?{9WG_ e%''y%Q d÷+ufG_1NK_k/Q=Xn(G*#b n%= ᯓ_{5lVR刖jIhlfbfpU? ~ɞcC??C5r 9|t௪~֟fMy:0ЂW ڬb, 5!|Q@F恣g ͈YBS|(»p,qɎ"\ϣ꽺U==S>}\_o뒿Uٛ[شymfmf9mޛOL%{+Ai3e nnBGoq~A=| >Yj~ٳf;>z̐oӿJNBْ&IR@ '} ̸wuz~fF aA hЙ>;P!{xOX8Q¿`ECX;l,5wx7]!|!X C8S)ϲp"fKzBVb8b Ӡg__!?_)ĹpOkM($B.m}Ap+Ғ?Š`mw`]Ӱ6I8 pnw4 á>dH+§XȇP 2#mV TTG4>EAp&** (1 6t7 AEqqAL@EEDp!:]0EE *N$UHLs}U~߂  aƐ`Ġ髉bXC>%>a| \Ǒ!W$}ۈ>峃{~"b!yz`Fj$\c܁gvarodXEgP8dg C0ϰ#nWL\xthǗ!T|3܃͍t')3R GQ _yNg͖֝>9%x3~MW=1TѳB_K [I}O/'} ۧ!ֲO/#ק9c~g0ɩW?H Ew-Ť֨OG9"Z=Dck(ieSQ >t¶уMwGqbx([~4c~~mpq歹ȵJ+=i^dQqqJa9Wf S?:I\&GWemv}ZW./&Z8LXnvmA} e[݂ f~iyz ,,~ܘ^X lK5a̒Qטwȗz/o ~ jEWw@bНZ\d"U.>_gu8}w.x^ّ3ol{5aRaUSLSgoß mմvy3{o3WXQ1}s_պJB%eK>/neʴujykMsJi3fyNsks\}7'Sl}vZ$ k_ׯ !҅m'~h{|e+ٕkyy +f洍Xk!4b֥#HR QٚQNjf;*1h~]olñkҌIsMܻq0[?`u{/^E0OWeֲ۴>*aU뷝>?]η}c4jI}͙kݞ7t㵎 ָ\uх]-]A_Vn~sf xģ)Dls3kʚ-\:nոH (\ep͐x^3">Uәh~~kQc ꇸ6끸늸ϽϷLq\1w{7K~q0,'ŐIeP,jx[ Tt36KT" ӵP$ QvPl8bWuGaRR@:=qIJNrD&5MVRI5`dHPs@,(JL.@jl!{& Q!3b#& psg,%*t#<\]ܜS5rgΉ>^q2amԓz\e' <]|\ܹfSKٟRcB$g&^,sҲ@W4]:O)tW&u EQ&Mg!͏[G{J% !0Bȧ)A<$B( H C&d Ȇհ6'.v(pA)TQP ':Kp hF>4A3<'Ϡ :%h-q0Z 08Gt@8 't8 pF"XGz܌[pnǝ߰w܋Eq ,ů,`^xoc#~x[)>v|]J<B-&c:.ñpV Vg3~PK/SB}rebar/ebin/rebar_xref.beam}Y tՙydމ'{G$R"{dَ8X8ۉb '5;pRMAZ2-(ӹ+ H4Zdfk\A.y%Q1L\Ԃ=MJ&_U$s\(O2Lfl޸~B·䐳rf (Ta]`8fl1pb,1ARNcDy!%ө,$/%%JcBAMNJE[PBhG2 %[1@㔜'bʸ<wPGN9h6W5%@y*Z AU4LgVF6DZgtVI4͢b(r*MU&MhY1ErEp!V=/j[\RXs>'U2ʔ-8̻=oOELNj IXV*b(s9i̗(Ȅx1;rL+JD$~g[i}s ~}-+O)\:{5HG8MryY"XY.4s |PT prTG1cӹMX(rVҺ!z-iAM뢝c$'!p^J1^R]D+9DAd:D+鐫&ӟ!W;1 IaʰwEz}tWa5c*qJL-/9 ß] ~#i瞪9p.){_KeĄpKVRd8pu%9﷉g8K޻if9'Q!grtݒ J!\7Kj D)H׈MґQm"\zcp=v\FN먶֜ R P vIGl+9$Ivdr"YPxFP q:Zp`CՕ*ȵ! g'[Cat"Hs./[wh]`Wϕ'%HN^GK`]*PA-Cvg X &FJ3gX::Yè$ʍ!;E!'()<X^ 1g):0L B( yB3-e0h0h@&Ilhʏ -xWW5\̍dܰ%.EvGCw<({A=A^x3B2'' t1  7[t4@^"U XUuC.+I7rv4Qh OWJb7pSPww9QV< rI7HJGE,'p!$9/ 4 AѰ/rCWР FhCWB7 ^ɛ7 {e#v^nnÛqBQS؞Vv1tEC8%f7Mph ]9DVl ]@*tt͎K{hC72TQ^$ KDd;}dLF;1>DvQu$R:qx$IMP#ka{i!+pO8rdu ^16Fq/p':IެMiPlM)չWQ&_.'[ qJfv?8szh5"&Lyʑ7| AyY#5G9XTА\cCEUT  u){/5}Sy. h)9/76udX0y'cyT Ɯ9oQo7k|)_ cRe`ʈ/7U`Vq%k-9'}2Y͖X;6XݖylI ZcbׂgmE>9L4S0D:HnlnbsJd00kw^ 'MLyLżS&.f:+vGOgLR9?H>hmG—޾̟oGWyn{hHb=~ͅXq?uyǒ[:vף7W<{:|$3~?}5w0_W_ֶՍ |\_vv#5#hҎѶkߖ|7H'G}w~_?竣?-Ӎn/ 7w(2oOW>!u7"OvT{{}v`6_XC_\󽊿0r;e5ɿ* /w _}o:K^^}3ıñ+]OK?nORd̎\wʽ!!m'>C+&>Y&]&c.s&&~#6syF!gdYĸ`tr5{>F'l9wR>9;kMyUwG*%(zZYzdghsG&A ޑ%Gb?FԔ@EXHINa@$$HgbBIP}AHPLpoǖ螾IE]kkk, D}Tc*]ZM/*>՗l%͡ hn{p}ZQ5}*omlR+َW Q^#ҟi')O wv-|) ~??Ə' ~?9<~ oweG~?ƟxTy8O{y<4|A\,PK/SBpriv/PK/SBpriv/templates/PK/SBjjDpriv/templates/basicnif.cU]o0}W\1J[ڽFy:"E҉ѾTei;2&HPuRy0}?=p@ẙK$C]V4@ MCB$*ă>IHU0q{z=wMBd+gT}gFlߥP˜dmVK᷾'?' < | |}?׾\L +*A $CΗ:-n ?x&ӄػׇKʷfmv受S9U/3Vs,1cDUdD|$Tw0S- QMm\k#Iyn`"*$SŖM+5gxqT潛tm+Oj:B_w&}-K(֬b{8x&amM"y IqFc-j`EH&dgzG^SL27]QU8VJI(OE[p.~!3M\GE_ j&<`=jtc4+#$Enx]*@5VvMHw`t<93?YD:JQIm8j"He㋫IΔOf! WA;.U#+,hP5UZbZrLJQ)D&S6H!$bRv tR֒}L7Qq |i*3GeуyYK}WL,I:54WYf_@1h`Ch?vOYr $0joߕ=isF +! B`.ݩuY YYKMkJ9;Hsi}ryrC3 |uE|V9K,i)U2GNy?(X?RSkwVJsQG,veSP*:f;J Al_\_E5p"8mA&@dt-p֓ZH \GJϯX0x)R!~7>WBh=B4jyRQ)۝*#f螽t%`@ҕBv-3B5(]c_|<44`δcv/#: G'[!'%+WU}r-?w6; xZYZ6=I<?qC\nNf$mbj7wi׍ٯ=vSe,Rz)s' MK'RMڱN d>vyT+fZ 9=?O2Wyp8":17y4=eovgskm*g]FbѰ>'V1K8 fy`X붾?w[j֫>g_ 4N*Lp8m:XiGf$\3 vwUytgB L42BPK/SB|:"priv/templates/simplenode.nodetoolXo6_qPTZ=(Ȱ.K[;$ݓgDŜeR |Nݑ%˲}>y/> y5piQ٣G`* p]2yuFB\QɯyeS3RM 6žzV^/!$Rk^V\å AH5ˬ@ nA)05c _+#p 2mS^-0cw~kI!3 Y7bx}#DUƍI2I K{!$f2X0Dgr%[@/$/%cC#Tl)Y WƬf9$Hg ,4k1}f `̆)Q5c(Yt ϵV:կ~S9$b|dt~&C0K<wԈbЬ mvhr S x![[Ҿj~Ty|9UXgʻM%"a1e S&6Wtεb59 yfSBۭeq|T(KsMK tNtԼ5yUxPqܦVA!t)ުNRTFGa% %Cx N%`ttP=9.U)+C]eIʲH/ej4ei`ֽ)0JQaƌ+M ]&Q`].*,E>g/UXU=I04_H0| L+9$gC(TY*DWK+.py 7i _?yrj39tjsmOB,4b$J%β*_{֤)ZBq6ҲiCVVv3`Wك4XQ֙ZH߄ _J5e9rRCơ^S;\ƩO ۪PN@P>]uړOEu >~Bc08c*2㉁Mt>5^3Jp]mk1G~mwk.q&0;,N$:\qf[׊99)B c4Ns7lxq^lٿ Q90!;SRooj2&Hwhy\Iw#H .m;${ ;tN )bϔz=u롍tDκ7 ^arG힉߅:he~[-t;Q~3joPK/SBژ\)(priv/templates/simplenode.reltool.configTn0^HmDZi%EOX`#ۉJ 4<33{?J xf`J gvr`FoƯ-e i(v) QE4JDL}Z^I1댬{e¶U8}g8{zX'pP?Yuܸ4/+_Wi3]zw-6z Tyv 0Nr:6`?)g XpP{ˁ/T?<)bţ'a LwBT':G#]'OB:Y(m \-YL_=?{e> hQ=.)/vȷ v^R!1!<ҋUI􃠔4N u>Cr[ot|l!E0\*-\ 'sWқ56FdA,n1L"a+bT1nR]kzPK/SB J $ priv/templates/simplenode.runnerYmsHίJؾI63/8d@g!f$cb_H!WUWG3ӯ bY9 3מ/ \6. {MD Ģ 5`q4#=/cpp97%#&14[Q"fm Wurl qR1?]5ӝ7}-pϿY< P=g/fw- f܋bqDVm'8K% +Qtxx>hGi`=h~/!Z`+k$4_φ-PFLR\mkxFuØs`w,~H+oF%VakЬ|uh!㠟DIL~ H*p*^}(:!\,-C`&"n᲻F>{y"%` Ȕ-CnDPIOlJ0'pa&Z7 4HZ{y3G4) b8f(&ΐ=U;-^0Y,5ɖT*{Fq mJ-|#c _QLfxBx10_p'0c ae8:ƭus2sreҧDC>fܯNL*h84"3/~o'R[/wtY]{HԜRjC};.g3f~Ebv9\2 47m+$RNL nF h{9$T<"tiޥQE!qwp=fq7:~-.elҰgb#0{ r^=@c[SaNx~l_W,^dF.H!xк1U b <\ɯ ݳNkhN؂jjDYD{:(=S4^>RҹzR_x=m.d-[!eA{60GƃVgxU?ǣ[h o-$wThr"=S"7Kĥ 19"d1֝p ď'xLԤ:yy@`72"Akz?ujk+}=*#9DJ(8N9y*B] 5t[,cJLj<'s ϝaKU c$Z Ij[i} YDʯ /qC_!]F6Vƽt78dX09!V $KE7l!$c:OY셁M21P"/I*m.)½1:~+ 5o+OR>y ?:> t 5ьsls3x9e6R&5lZVۣvj=jF&p=Lhe"sCI TM~?>Ju i礤NYzX|fҋs Ԁ/'[ȪuReHv7a|-gp|w^BC{';7@_O2Luyg( vrRi %{,M?’\^z󸴪:^uUw"YDv2ɤ2۷e=|_(#9F{( pfyoNg?emCkZs^sֽ>+NBfTRrkBi'tζ `Ila+sn*gkl8z #}v3ߋUlġҒ._nP3IkOk:yf΂eiuǙo ч,=W]Qk-tn#]3?q @x} C6{T~/pI1ᇞH2w5Ч'yqJzx컫oczF VATi3LY ؼuZ@Uʛ +)+>1/5cHhMq$[aQ}TBau'~5Ac~[+g>B$]obVkIT^o}jvn"AL9wqAw P~Oᮗչil?]x-)&_6 Fwh.R}F\[o  l5elo/` X|+ Xh{{5u/U,x/~(o D B.&\ 9g11$zVMסj>%dI'MQbYS]o0}ϯbbؖ64/[E PKlSm+@ 4x|8M T5y-v3`63}eKؾ)V*[Q;L5rBE/Pf@Il*Q=rͥe䯂`u,7? "cײ䢬 ]m_׏R`- s r% C{4X$v٧~sbF 5Ao`e#?˕sfqo:iԢjS{8c=h ʲV16Y.-wXwyY&RhjL=^We->H^kAfIOPK/SB8&M$priv/templates/simplenode.sys.config}0> I#! b!$`M 8p #9%1 }/amRyG*c*en@@z3+IΉٖ|2e?KDm)oQ'>=XWP6͟׾SV`az'c|~eX#L;cٚ7PK/SBT_"priv/templates/simplenode.templateuM0 R`1w(Ri޼M;3$+u0:3ko'tAGj r*VZS& Hh-U [G)h|h_<_(: )I±FBg8L#>`*0,d j6h֖`>FrXp< `3f||BN5:ֶi@Q *܂;2>v!!-U Դ%^'-\xkȐ6OGq{1ygpս9[T5< -@Z?+'pOM~PK/SB;k/' ,priv/templates/simplenode.windows.runner.cmdVMo8WX$hmr4 wEY^khD$$߾3")S`sy3z|AN *Y$Ix!Y'-g0iސlלQrevMj7LsiI%4/ҏZk" a^!|[NR6K&KoHZZ4&O "/}RrJ_=ok 70i`i sm*w{Kb,Ӷ*fّ+70.M~:fS~dVpmM@ =\zM tCg&C2(\뎀6*]R}=*%4m}Zլ a䊔JmwYڦoy&}(}ߖBVrAf#CԋKoZt+&T$~2W9q 0pH7jyJ z̶؈^E{ۃFdGV>&l@W*sОxJ&+]V!!u~LvѷѨM͛VY/cVU0}c0ʬe:ݪ'vYu- /׊|%0jo)I^rcB_{Wq~?2?ǙZƿc5|v9r|A-Sׯ]=b:C$u[4c˦rvo{QJ]Pªи)YDddԋ81$`2=7;  G7Իm]\fi_;0Ԟl ^Ŀ9@ U tAq^A{T)(]w튥{L\Q;8hۂ?&AYߛR74{iE߼n0:#t2E7Pp& a rprP_f:!< r qKiga &!Yn`.aÃQ >ߐs|kY*"@lr)\Y.OJ*@Y O+ެD 0zPK/SB~a/priv/templates/simplenode.windows.start_erl.cmdTj0+@Ҥ^ڽ nDԖ\IͶ#۱в|(PBBd'Pnڐ >rwZG-ᲶJ;`Jzǰ'q?̶^m SǷwTYB@TƧ>z]=h \Bi![_ľNq}pgypcKʍjzDt| P9;bXtDgmX^{h;Ձ@t>u%'ڥ8bps<vC|l2>ֺh>(rTR0uV/O8w %OpqrGePęGKkf&Zb[敮#4ȕq5PͺzӼfwTz'amgb T>w!>g$񱜸>4$rfvS&wpg8N+}: \8܆B ՏR_ PK/SBٖ\priv/templates/simplesrv.erlR]k0}ȋ!] ġk %8J Zrs9{ *<7ē؉L$5O{[./24^c z=x3\IJ[{…eR>]~莠aBDZhlt_\n },̂/ڨ!\i Ѡݍ4yqmmˀ t.ۑ P>W{KƩy9g`,AtՁuW8 GA_2 NM $ )dFIcfSLg"Yy%qjBߚZLt'PK/SBZ`JV!priv/templates/simplesrv.template.K,LLI-Q..*LQPʭ,N-*K-R.I-I,Ig@uzE9J djZ PPK/SBrebar/PK/SB $rebar/ebin/PK/SBOv-Mrebar/ebin/getopt.beamPK/SB&c:Urebar/ebin/mustache.beamPK/SB@l +rebar/ebin/rebar.appPK/SB!c.rebar/ebin/rebar.beamPK/SB.$Frebar/ebin/rebar_abnfc_compiler.beamPK/SB@2 <hMrebar/ebin/rebar_app_utils.beamPK/SB*0 0Wrebar/ebin/rebar_appups.beamPK/SB/f3X #drebar/ebin/rebar_asn1_compiler.beamPK/SB#krebar/ebin/rebar_base_compiler.beamPK/SBaG'Pzrebar/ebin/rebar_cleaner.beamPK/SB]~rebar/ebin/rebar_config.beamPK/SBCԭD2irebar/ebin/rebar_core.beamPK/SB1<Nrebar/ebin/rebar_ct.beamPK/SBy@X"%d<erebar/ebin/rebar_deps.beamPK/SBD7f "rebar/ebin/rebar_dia_compiler.beamPK/SB! .h erebar/ebin/rebar_edoc.beamPK/SBI+#rebar/ebin/rebar_erlc_compiler.beamPK/SBG&( rebar/ebin/rebar_erlydtl_compiler.beamPK/SB U ~rebar/ebin/rebar_escripter.beamPK/SBi>;+H'rebar/ebin/rebar_eunit.beamPK/SBq~Q  Srebar/ebin/rebar_file_utils.beamPK/SBQ"tR"?^rebar/ebin/rebar_lfe_compiler.beamPK/SBwcrebar/ebin/rebar_log.beamPK/SBR &hrebar/ebin/rebar_neotoma_compiler.beamPK/SBSx[ \srebar/ebin/rebar_otp_app.beamPK/SBz7.#~rebar/ebin/rebar_port_compiler.beamPK/SB3 )<rebar/ebin/rebar_protobuffs_compiler.beamPK/SBv <rebar/ebin/rebar_qc.beamPK/SB<#X rebar/ebin/rebar_rel_utils.beamPK/SBLirebar/ebin/rebar_require_vsn.beamPK/SBZო~^rebar/ebin/rebar_shell.beamPK/SB! rebar/ebin/rebar_subdirs.beamPK/SB~#ʞf!rebar/ebin/rebar_templater.beamPK/SB  rebar/ebin/rebar_upgrade.beamPK/SB. IåT+rebar/ebin/rebar_utils.beamPK/SB}#rebar/ebin/rebar_xref.beamPK/SBx4priv/PK/SB4priv/templates/PK/SBjjD4priv/templates/basicnif.cPK/SBzC7priv/templates/basicnif.erlPK/SB+R 9priv/templates/basicnif.templatePK/SBȪ89priv/templates/ctsuite.erlPK/SB}OP_>priv/templates/ctsuite.templatePK/SBv ?priv/templates/simpleapp.app.srcPK/SByE\!7@priv/templates/simpleapp.templatePK/SBk @priv/templates/simpleapp_app.erlPK/SB# Apriv/templates/simpleapp_sup.erlPK/SB"'Cpriv/templates/simplefsm.erlPK/SBDrFS!Dpriv/templates/simplefsm.templatePK/SB49ALEpriv/templates/simplemod.erlPK/SB6V!Epriv/templates/simplemod.templatePK/SB+]I;D"TFpriv/templates/simplemod_tests.erlPK/SB$Fpriv/templates/simplenode.erl.scriptPK/SB?6X81Jpriv/templates/simplenode.install_upgrade.escriptPK/SB|:"Lpriv/templates/simplenode.nodetoolPK/SBژ\)(Spriv/templates/simplenode.reltool.configPK/SB J $ Upriv/templates/simplenode.runnerPK/SB8&M$cpriv/templates/simplenode.sys.configPK/SBT_"cpriv/templates/simplenode.templatePK/SBW8!epriv/templates/simplenode.vm.argsPK/SB;k/' ,yfpriv/templates/simplenode.windows.runner.cmdPK/SB~a/jpriv/templates/simplenode.windows.start_erl.cmdPK/SBٖ\=mpriv/templates/simplesrv.erlPK/SBZ`JV!npriv/templates/simplesrv.templatePKCC\oelixir-lang-1.1.0~0.20150708/rebar.config000066400000000000000000000012401254730255300173740ustar00rootroot00000000000000%% Using elixir as a rebar dependency %% This configuration file only exists so Elixir can be used %% as a rebar dependency, the same happens for the file %% src/elixir.app.src. %% In practice, Elixir is structured as OTP where many applications %% are placed in the lib directory. Since this structure is not %% supported by default by rebar, after adding Elixir as a dependency %% you need to explicitly add it to lib_dirs: %% %% {lib_dirs, [ %% "deps/elixir/lib" %% ]}. %% %% Run make as the proper compilation step {post_hooks, [{compile, "make compile"}]}. %% This prevents rebar_elixir_plugin from recompiling Elixir {ex_opts, [{src_dirs, [".PHONY"]}]}. elixir-lang-1.1.0~0.20150708/src/000077500000000000000000000000001254730255300157045ustar00rootroot00000000000000elixir-lang-1.1.0~0.20150708/src/elixir.app.src000066400000000000000000000003701254730255300204700ustar00rootroot00000000000000{application, elixir, [{description, "elixir"}, {vsn, "1.1.0-dev"}, {modules, [ elixir ]}, {registered, [elixir_config, elixir_code_server]}, {applications, [kernel,stdlib,compiler]}, {mod, {elixir,[]}}, {env, [{ansi_enabled, false}]} ]}.