diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-12-20 23:01:54 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-12-22 11:50:09 +0900 |
commit | 112ca8677b9b024de5529712e559c968da40a67a (patch) | |
tree | a8e93a0b05d61aeaab1dab3288c5fc518cdd05c6 /debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d | |
parent | b37f44d6c7444ca20c48a07fdcaf7b2a812db5bd (diff) | |
download | extra-dependencies-112ca8677b9b024de5529712e559c968da40a67a.tar.gz extra-dependencies-112ca8677b9b024de5529712e559c968da40a67a.zip |
DEB uncrustify: added first version of uncrustify-trinity. This is basically the upstream 0.72.0 version of uncrustify, repackaged.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d')
43 files changed, 6874 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40000-HashMap.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40000-HashMap.d new file mode 100644 index 00000000..74d0614b --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40000-HashMap.d @@ -0,0 +1,1095 @@ +/******************************************************************************* + + @file HashMap.d + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for damages + of any kind arising from the use of this software. + + Permission is hereby granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and/or + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment within documentation of + said product would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any distribution + of the source. + + 4. Derivative works are permitted, but they must carry this notice + in full and credit the original source. + + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + Written by Doug Lea with assistance from members of JCP JSR-166 + Expert Group and released to the public domain, as explained at + http://creativecommons.org/licenses/publicdomain + + @version Initial version, July 2004 + @author Doug Lea; ported/modified by Kris + +*******************************************************************************/ + +module mango.cache.HashMap; + +/****************************************************************************** + +******************************************************************************/ + +extern (C) +{ +int memcmp(char *, char *, uint); +} + + +/** + * A hash table supporting full concurrency of retrievals and + * adjustable expected concurrency for updates. This class obeys the + * same functional specification as {@link java.util.Hashtable}, and + * includes versions of methods corresponding to each method of + * <tt>Hashtable</tt>. However, even though all operations are + * thread-safe, retrieval operations do <em>not</em> entail locking, + * and there is <em>not</em> any support for locking the entire table + * in a way that prevents all access. This class is fully + * interoperable with <tt>Hashtable</tt> in programs that rely on its + * thread safety but not on its synchronization details. + * + * <p> Retrieval operations (including <tt>get</tt>) generally do not + * block, so may overlap with update operations (including + * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results + * of the most recently <em>completed</em> update operations holding + * upon their onset. For aggregate operations such as <tt>putAll</tt> + * and <tt>clear</tt>, concurrent retrievals may reflect insertion or + * removal of only some entries. Similarly, Iterators and + * Enumerations return elements reflecting the state of the hash table + * at some point at or since the creation of the iterator/enumeration. + * They do <em>not</em> throw + * {@link ConcurrentModificationException}. However, iterators are + * designed to be used by only one thread at a time. + * + * <p> The allowed concurrency among update operations is guided by + * the optional <tt>concurrencyLevel</tt> constructor argument + * (default 16), which is used as a hint for internal sizing. The + * table is internally partitioned to try to permit the indicated + * number of concurrent updates without contention. Because placement + * in hash tables is essentially random, the actual concurrency will + * vary. Ideally, you should choose a value to accommodate as many + * threads as will ever concurrently modify the table. Using a + * significantly higher value than you need can waste space and time, + * and a significantly lower value can lead to thread contention. But + * overestimates and underestimates within an order of magnitude do + * not usually have much noticeable impact. A value of one is + * appropriate when it is known that only one thread will modify and + * all others will only read. Also, resizing this or any other kind of + * hash table is a relatively slow operation, so, when possible, it is + * a good idea to provide estimates of expected table sizes in + * constructors. + * + * <p>This class and its views and iterators implement all of the + * <em>optional</em> methods of the {@link Map} and {@link Iterator} + * interfaces. + * + * <p> Like {@link java.util.Hashtable} but unlike {@link + * java.util.HashMap}, this class does NOT allow <tt>null</tt> to be + * used as a key or value. + * + * <p>This class is a member of the + * <a href="{@docRoot}/../guide/collections/index.html"> + * Java Collections Framework</a>. + * + * @since 1.5 + * @author Doug Lea + * @param <K> the type of keys maintained by this map + * @param <V> the type of mapped values + */ + +class HashMap +{ + alias void[] K; + alias Object V; + alias jhash hash; // jhash, fnv, or walter + + /* + * The basic strategy is to subdivide the table among Segments, + * each of which itself is a concurrently readable hash table. + */ + + /* ---------------- Constants -------------- */ + + /** + * The default initial number of table slots for this table. + * Used when not otherwise specified in constructor. + */ + private const uint DEFAULT_INITIAL_CAPACITY = 16; + + /** + * The maximum capacity, used if a higher value is implicitly + * specified by either of the constructors with arguments. MUST + * be a power of two <= 1<<30 to ensure that entries are indexible + * using ints. + */ + private const uint MAXIMUM_CAPACITY = 1 << 30; + + /** + * The default load factor for this table. Used when not + * otherwise specified in constructor. + */ + private const float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The default number of concurrency control segments. + **/ + private const uint DEFAULT_SEGMENTS = 16; + + /** + * The maximum number of segments to allow; used to bound + * constructor arguments. + */ + private const uint MAX_SEGMENTS = 1 << 16; // slightly conservative + + + /* ---------------- Fields -------------- */ + + /** + * Mask value for indexing into segments. The upper bits of a + * key's hash code are used to choose the segment. + **/ + private final int segmentMask; + + /** + * Shift value for indexing within segments. + **/ + private final int segmentShift; + + /** + * The segments, each of which is a specialized hash table + */ + private final Segment[] segments; + + + /* ---------------- Small Utilities -------------- */ + + /** + * Returns a hash code for non-null Object x. + * Uses the same hash code spreader as most other java.util hash tables. + * @param x the object serving as a key + * @return the hash code + */ + private static final uint walter(K x) + { + uint h = typeid(char[]).getHash(&x); + + h += ~(h << 9); + h ^= (h >>> 14); + h += (h << 4); + h ^= (h >>> 10); + return h; + } + + /** + * Returns a hash code for non-null Object x. + * uses the FNV hash function + * @param x the object serving as a key + * @return the hash code + */ + private static final uint fnv(K x) + { + uint hash = 2_166_136_261; + + foreach (ubyte c; cast(ubyte[])x) + { + hash ^= c; + hash *= 16_777_619; + } + return hash; + } + + + + /** + * hash() -- hash a variable-length key into a 32-bit value + * k : the key (the unaligned variable-length array of bytes) + * len : the length of the key, counting by bytes + * level : can be any 4-byte value + * Returns a 32-bit value. Every bit of the key affects every bit of + * the return value. Every 1-bit and 2-bit delta achieves avalanche. + * About 36+6len instructions. + * + * The best hash table sizes are powers of 2. There is no need to do + * mod a prime (mod is sooo slow!). If you need less than 32 bits, + * use a bitmask. For example, if you need only 10 bits, do + * h = (h & hashmask(10)); + * In which case, the hash table should have hashsize(10) elements. + * + * If you are hashing n strings (ub1 **)k, do it like this: + * for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); + * + * By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this + * code any way you wish, private, educational, or commercial. It's free. + * + * See http://burlteburtle.net/bob/hash/evahash.html + * Use for hash table lookup, or anything where one collision in 2^32 is + * acceptable. Do NOT use for cryptographic purposes. + */ + + static final uint jhash(K x) + { + ubyte *k; + uint a, + b, + c, + len; + + len = x.length; + k = cast(ubyte *)x; + a = b = 0x9e3779b9; + + // the previous hash value + c = 0; + + // handle most of the key + while (len >= 12) + { + a += *cast(uint *)(k + 0); + b += *cast(uint *)(k + 4); + c += *cast(uint *)(k + 8); + + a -= b; a -= c; a ^= (c >> 13); + b -= c; b -= a; b ^= (a << 8); + c -= a; c -= b; c ^= (b >> 13); + a -= b; a -= c; a ^= (c >> 12); + b -= c; b -= a; b ^= (a << 16); + c -= a; c -= b; c ^= (b >> 5); + a -= b; a -= c; a ^= (c >> 3); + b -= c; b -= a; b ^= (a << 10); + c -= a; c -= b; c ^= (b >> 15); + k += 12; len -= 12; + } + + // handle the last 11 bytes + c += x.length; + switch (len) + { + case 11: c += (cast(uint)k[10] << 24); + + case 10: c += (cast(uint)k[9] << 16); + + case 9: c += (cast(uint)k[8] << 8); + + case 8: b += (cast(uint)k[7] << 24); + + case 7: b += (cast(uint)k[6] << 16); + + case 6: b += (cast(uint)k[5] << 8); + + case 5: b += k[4]; + + case 4: a += (cast(uint)k[3] << 24); + + case 3: a += (cast(uint)k[2] << 16); + + case 2: a += (cast(uint)k[1] << 8); + + case 1: a += k[0]; + + default: + } + + a -= b; a -= c; a ^= (c >> 13); + b -= c; b -= a; b ^= (a << 8); + c -= a; c -= b; c ^= (b >> 13); + a -= b; a -= c; a ^= (c >> 12); + b -= c; b -= a; b ^= (a << 16); + c -= a; c -= b; c ^= (b >> 5); + a -= b; a -= c; a ^= (c >> 3); + b -= c; b -= a; b ^= (a << 10); + c -= a; c -= b; c ^= (b >> 15); + + return c; + } + + + /** + * Returns the segment that should be used for key with given hash + * @param hash the hash code for the key + * @return the segment + */ + private final Segment segmentFor(uint hash) + { + return segments[(hash >>> segmentShift) & segmentMask]; + } + + /* ---------------- Inner Classes -------------- */ + + /** + * ConcurrentHashMap list entry. Note that this is never exported + * out as a user-visible Map.Entry. + * + * Because the value field is volatile, not final, it is legal wrt + * the Java Memory Model for an unsynchronized reader to see null + * instead of initial value when read via a data race. Although a + * reordering leading to this is not likely to ever actually + * occur, the Segment.readValueUnderLock method is used as a + * backup in case a null (pre-initialized) value is ever seen in + * an unsynchronized access method. + */ + private static class HashEntry + { + final K key; + final uint hash; + final V value; + final HashEntry next; + + this(K key, uint hash, HashEntry next, V value) + { + this.key = key; + this.hash = hash; + this.next = next; + this.value = value; + } + } + + /** + * Segments are specialized versions of hash tables. This + * subclasses from ReentrantLock opportunistically, just to + * simplify some locking and avoid separate construction. + **/ + static class Segment + { + /* + * Segments maintain a table of entry lists that are ALWAYS + * kept in a consistent state, so can be read without locking. + * Next fields of nodes are immutable (final). All list + * additions are performed at the front of each bin. This + * makes it easy to check changes, and also fast to traverse. + * When nodes would otherwise be changed, new nodes are + * created to replace them. This works well for hash tables + * since the bin lists tend to be short. (The average length + * is less than two for the default load factor threshold.) + * + * Read operations can thus proceed without locking, but rely + * on selected uses of volatiles to ensure that completed + * write operations performed by other threads are + * noticed. For most purposes, the "count" field, tracking the + * number of elements, serves as that volatile variable + * ensuring visibility. This is convenient because this field + * needs to be read in many read operations anyway: + * + * - All (unsynchronized) read operations must first read the + * "count" field, and should not look at table entries if + * it is 0. + * + * - All (synchronized) write operations should write to + * the "count" field after structurally changing any bin. + * The operations must not take any action that could even + * momentarily cause a concurrent read operation to see + * inconsistent data. This is made easier by the nature of + * the read operations in Map. For example, no operation + * can reveal that the table has grown but the threshold + * has not yet been updated, so there are no atomicity + * requirements for this with respect to reads. + * + * As a guide, all critical volatile reads and writes to the + * count field are marked in code comments. + */ + + /** + * The number of elements in this segment's region. + **/ + int count; + + /** + * The table is rehashed when its size exceeds this threshold. + * (The value of this field is always (int)(capacity * + * loadFactor).) + */ + int threshold; + + /** + * The per-segment table. Declared as a raw type, casted + * to HashEntry<K,V> on each use. + */ + HashEntry[] table; + + /** + * The load factor for the hash table. Even though this value + * is same for all segments, it is replicated to avoid needing + * links to outer object. + * @serial + */ + final float loadFactor; + + this(int initialCapacity, float lf) + { + loadFactor = lf; + setTable(new HashEntry[initialCapacity]); + } + + /** + * Set table to new HashEntry array. + * Call only while holding lock or in constructor. + **/ + private final void setTable(HashEntry[] newTable) + { + threshold = cast(int)(newTable.length * loadFactor); + volatile table = newTable; + } + + /** + * Return properly casted first entry of bin for given hash + */ + private final HashEntry getFirst(uint hash) + { + HashEntry[] tab; + + volatile tab = table; + return tab[hash & (tab.length - 1)]; + } + + /** + * Return true if the two keys match + */ + private static final bool matchKey(K a, K b) + { + if (a.length == b.length) + return cast(bool)(memcmp(cast(char *)a, cast(char *)b, a.length) == 0); + + return false; + } + + /* Specialized implementations of map methods */ + + final V get(K key, uint hash) + { + int c; + + // read-volatile + volatile c = count; + if (c) + { + HashEntry e = getFirst(hash); + while (e) + { + if (hash == e.hash && matchKey(key, e.key)) + { + V v; + volatile v = e.value; + if (v) + return v; + + synchronized (this) + return e.value; + } + e = e.next; + } + } + return null; + } + + + final bool containsKey(K key, uint hash) + { + int c; + + // read-volatile + volatile c = count; + if (c) + { + HashEntry e = getFirst(hash); + while (e) + { + if (e.hash == hash && matchKey(key, e.key)) + return true; + + e = e.next; + } + } + return false; + } + + + + final synchronized V replace(K key, uint hash, V newValue) + { + HashEntry e = getFirst(hash); + + while (e && (e.hash != hash || !matchKey(key, e.key))) + e = e.next; + + V oldValue = null; + + if (e) + volatile + { + oldValue = e.value; + e.value = newValue; + } + return oldValue; + } + + + final synchronized V put(K key, uint hash, V value, bool onlyIfAbsent) + { + int c; + + volatile c = count; + if (c++ > threshold) + rehash(); + + HashEntry[] tab; + volatile tab = table; + uint index = hash & (tab.length - 1); + HashEntry first = tab[index]; + HashEntry e = first; + + while (e && (e.hash != hash || !matchKey(key, e.key))) + e = e.next; + + V oldValue; + + if (e) + { + volatile oldValue = e.value; + if (!onlyIfAbsent) + volatile e.value = value; + } + else + { + oldValue = null; + tab[index] = new HashEntry(key, hash, first, value); + + // write-volatile + volatile count = c; + } + return oldValue; + } + + + private final void rehash() + { + HashEntry[] oldTable; + + volatile oldTable = table; + int oldCapacity = oldTable.length; + + if (oldCapacity >= MAXIMUM_CAPACITY) + return; + + /* + * Reclassify nodes in each list to new Map. Because we are + * using power-of-two expansion, the elements from each bin + * must either stay at same index, or move with a power of two + * offset. We eliminate unnecessary node creation by catching + * cases where old nodes can be reused because their next + * fields won't change. Statistically, at the default + * threshold, only about one-sixth of them need cloning when + * a table doubles. The nodes they replace will be garbage + * collectable as soon as they are no longer referenced by any + * reader thread that may be in the midst of traversing table + * right now. + */ + + HashEntry[] newTable = new HashEntry[oldCapacity << 1]; + threshold = cast(int)(newTable.length * loadFactor); + int sizeMask = newTable.length - 1; + + for (int i = 0; i < oldCapacity; ++i) + { + // We need to guarantee that any existing reads of old Map can + // proceed. So we cannot yet null out each bin. + HashEntry e = oldTable[i]; + + if (e) + { + HashEntry next = e.next; + uint idx = e.hash & sizeMask; + + // Single node on list + if (next is null) + newTable[idx] = e; + else + { + // Reuse trailing consecutive sequence at same slot + HashEntry lastRun = e; + int lastIdx = idx; + for (HashEntry last = next; last; last = last.next) + { + uint k = last.hash & sizeMask; + if (k != lastIdx) + { + lastIdx = k; + lastRun = last; + } + } + newTable[lastIdx] = lastRun; + + // Clone all remaining nodes + for (HashEntry p = e; p !is lastRun; p = p.next) + { + uint k = p.hash & sizeMask; + HashEntry n = newTable[k]; + newTable[k] = new HashEntry(p.key, p.hash, n, p.value); + } + } + } + } + volatile table = newTable; + } + + /** + * Remove; match on key only if value null, else match both. + */ + final synchronized V remove(K key, uint hash, V value) + { + int c; + + HashEntry[] tab; + + volatile c = count - 1; + volatile tab = table; + + uint index = hash & (tab.length - 1); + HashEntry first = tab[index]; + HashEntry e = first; + + while (e && (e.hash != hash || !matchKey(key, e.key))) + e = e.next; + + V oldValue = null; + + if (e) + { + V v; + volatile v = e.value; + if (value is null || value == v) + { + oldValue = v; + + // All entries following removed node can stay + // in list, but all preceding ones need to be + // cloned. + HashEntry newFirst = e.next; + for (HashEntry p = first; p !is e; p = p.next) + newFirst = new HashEntry(p.key, p.hash, newFirst, p.value); + tab[index] = newFirst; + + // write-volatile + volatile count = c; + } + } + return oldValue; + } + + + final synchronized void clear() + { + if (count) + { + HashEntry[] tab; + volatile tab = table; + + for (int i = 0; i < tab.length; i++) + tab[i] = null; + + // write-volatile + volatile count = 0; + } + } + } + + + + /* ---------------- Public operations -------------- */ + + /** + * Creates a new, empty map with the specified initial + * capacity and the specified load factor. + * + * @param initialCapacity the initial capacity. The implementation + * performs internal sizing to accommodate this many elements. + * @param loadFactor the load factor threshold, used to control resizing. + * @param concurrencyLevel the estimated number of concurrently + * updating threads. The implementation performs internal sizing + * to try to accommodate this many threads. + * @throws IllegalArgumentException if the initial capacity is + * negative or the load factor or concurrencyLevel are + * nonpositive. + */ + public this(uint initialCapacity, float loadFactor, uint concurrencyLevel) + { + assert(loadFactor > 0); + + if (concurrencyLevel > MAX_SEGMENTS) + concurrencyLevel = MAX_SEGMENTS; + + // Find power-of-two sizes best matching arguments + int sshift = 0; + int ssize = 1; + while (ssize < concurrencyLevel) + { + ++sshift; + ssize <<= 1; + } + + segmentShift = 32 - sshift; + segmentMask = ssize - 1; + this.segments = new Segment[ssize]; + + if (initialCapacity > MAXIMUM_CAPACITY) + initialCapacity = MAXIMUM_CAPACITY; + + int c = initialCapacity / ssize; + if (c * ssize < initialCapacity) + ++c; + + int cap = 1; + while (cap < c) + cap <<= 1; + + for (int i = 0; i < this.segments.length; ++i) + this.segments[i] = new Segment(cap, loadFactor); + } + + /** + * Creates a new, empty map with the specified initial + * capacity, and with default load factor and concurrencyLevel. + * + * @param initialCapacity The implementation performs internal + * sizing to accommodate this many elements. + * @throws IllegalArgumentException if the initial capacity of + * elements is negative. + */ + public this(uint initialCapacity) + { + this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); + } + + /** + * Creates a new, empty map with a default initial capacity, + * load factor, and concurrencyLevel. + */ + public this() + { + this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); + } + + /** + * Returns the value to which the specified key is mapped in this table. + * + * @param key a key in the table. + * @return the value to which the key is mapped in this table; + * <tt>null</tt> if the key is not mapped to any value in + * this table. + * @throws NullPointerException if the key is + * <tt>null</tt>. + */ + public V get(K key) + { + uint hash = hash(key); // throws NullPointerException if key null + + return segmentFor(hash).get(key, hash); + } + + /** + * Tests if the specified object is a key in this table. + * + * @param key possible key. + * @return <tt>true</tt> if and only if the specified object + * is a key in this table, as determined by the + * <tt>equals</tt> method; <tt>false</tt> otherwise. + * @throws NullPointerException if the key is + * <tt>null</tt>. + */ + public bool containsKey(K key) + { + uint hash = hash(key); // throws NullPointerException if key null + + return segmentFor(hash).containsKey(key, hash); + } + + /** + * Maps the specified <tt>key</tt> to the specified + * <tt>value</tt> in this table. Neither the key nor the + * value can be <tt>null</tt>. + * + * <p> The value can be retrieved by calling the <tt>get</tt> method + * with a key that is equal to the original key. + * + * @param key the table key. + * @param value the value. + * @return the previous value of the specified key in this table, + * or <tt>null</tt> if it did not have one. + * @throws NullPointerException if the key or value is + * <tt>null</tt>. + */ + public V put(K key, V value) + { + assert(value); + + uint hash = hash(key); + + return segmentFor(hash).put(key, hash, value, false); + } + + /** + * If the specified key is not already associated + * with a value, associate it with the given value. + * This is equivalent to + * <pre> + * if (!map.containsKey(key)) + * return map.put(key, value); + * else + * return map.get(key); + * </pre> + * Except that the action is performed atomically. + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * @return previous value associated with specified key, or <tt>null</tt> + * if there was no mapping for key. + * @throws NullPointerException if the specified key or value is + * <tt>null</tt>. + */ + public V putIfAbsent(K key, V value) + { + assert(value); + + uint hash = hash(key); + + return segmentFor(hash).put(key, hash, value, true); + } + + + /** + * Removes the key (and its corresponding value) from this + * table. This method does nothing if the key is not in the table. + * + * @param key the key that needs to be removed. + * @return the value to which the key had been mapped in this table, + * or <tt>null</tt> if the key did not have a mapping. + * @throws NullPointerException if the key is + * <tt>null</tt>. + */ + public V remove(K key) + { + uint hash = hash(key); + + return segmentFor(hash).remove(key, hash, null); + } + + /** + * Remove entry for key only if currently mapped to given value. + * Acts as + * <pre> + * if (map.get(key).equals(value)) { + * map.remove(key); + * return true; + * } else return false; + * </pre> + * except that the action is performed atomically. + * @param key key with which the specified value is associated. + * @param value value associated with the specified key. + * @return true if the value was removed + * @throws NullPointerException if the specified key is + * <tt>null</tt>. + */ + public bool remove(K key, V value) + { + uint hash = hash(key); + + return cast(bool)(segmentFor(hash).remove(key, hash, value) !is null); + } + + + /** + * Replace entry for key only if currently mapped to some value. + * Acts as + * <pre> + * if ((map.containsKey(key)) { + * return map.put(key, value); + * } else return null; + * </pre> + * except that the action is performed atomically. + * @param key key with which the specified value is associated. + * @param value value to be associated with the specified key. + * @return previous value associated with specified key, or <tt>null</tt> + * if there was no mapping for key. + * @throws NullPointerException if the specified key or value is + * <tt>null</tt>. + */ + public V replace(K key, V value) + { + assert(value); + + uint hash = hash(key); + + return segmentFor(hash).replace(key, hash, value); + } + + + /** + * Removes all mappings from this map. + */ + public void clear() + { + for (int i = 0; i < segments.length; ++i) + segments[i].clear(); + } + + + /** + * Returns an enumeration of the keys in this table. + * + * @return an enumeration of the keys in this table. + * @see #keySet + */ + public KeyIterator keys() + { + return new KeyIterator(this); + } + + /** + * Returns an enumeration of the values in this table. + * + * @return an enumeration of the values in this table. + * @see #values + */ + public ValueIterator elements() + { + return new ValueIterator(this); + } + + /********************************************************************** + + Iterate over all keys in hashmap + + **********************************************************************/ + + int opApply(int delegate(inout char[]) dg) + { + int result = 0; + KeyIterator iterator = keys(); + + while (iterator.hasNext) + { + char[] ca = cast(char[])iterator.next; + if ((result = dg(ca)) != 0) + break; + } + return result; + } + + /********************************************************************** + + Iterate over all keys in hashmap + + **********************************************************************/ + + int opApply(int delegate(inout char[], inout Object) dg) + { + int result = 0; + KeyIterator iterator = keys(); + + while (iterator.hasNext) + { + HashEntry he = iterator.nextElement; + char[] ca = cast(char[])he.key; + if ((result = dg(ca, he.value)) != 0) + break; + } + return result; + } + + + /* ---------------- Iterator Support -------------- */ + + abstract static class HashIterator + { + int nextSegmentIndex; + int nextTableIndex; + HashEntry[] currentTable; + HashEntry nextEntry; + HashEntry lastReturned; + HashMap map; + + this(HashMap map) + { + this.map = map; + nextSegmentIndex = map.segments.length - 1; + nextTableIndex = -1; + advance(); + } + + final void advance() + { + if (nextEntry !is null && (nextEntry = nextEntry.next) !is null) + return; + + while (nextTableIndex >= 0) + { + if ((nextEntry = currentTable[nextTableIndex--]) !is null) + return; + } + + while (nextSegmentIndex >= 0) + { + Segment seg = map.segments[nextSegmentIndex--]; + volatile if (seg.count) + { + currentTable = seg.table; + for (int j = currentTable.length - 1; j >= 0; --j) + { + if ((nextEntry = currentTable[j]) !is null) + { + nextTableIndex = j - 1; + return; + } + } + } + } + } + + public bool hasNext() + { + return cast(bool)(nextEntry !is null); + } + + HashEntry nextElement() + { + if (nextEntry is null) + throw new Exception("no such element in HashMap"); + + lastReturned = nextEntry; + advance(); + return lastReturned; + } + } + + static class KeyIterator : HashIterator + { + this(HashMap map) { + super(map); + } + public K next() + { + return super.nextElement().key; + } + } + + static class ValueIterator : HashIterator + { + this(HashMap map) { + super(map); + } + public V next() + { + volatile return super.nextElement().value; + } + } +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40001-imports.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40001-imports.d new file mode 100644 index 00000000..9f12a88e --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40001-imports.d @@ -0,0 +1,8 @@ + +private import mango.cache.Payload; + +private import mango.io.Exception, + mango.io.PickleRegistry; + +public import mango.cluster.model.ICluster; + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40002-volatile.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40002-volatile.d new file mode 100644 index 00000000..4dbd66dc --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40002-volatile.d @@ -0,0 +1,27 @@ +void foo(void) +{ + while (nextSegmentIndex >= 0) + { + Segment seg = map.segments[nextSegmentIndex--]; + volatile if (seg.count) + { + currentTable = seg.table; + for (int j = currentTable.length - 1; j >= 0; --j) + { + if ((nextEntry = currentTable[j]) !is null) + { + nextTableIndex = j - 1; + return; + } + } + } + } + + if (e) + volatile + { + oldValue = e.value; + e.value = newValue; + } + return oldValue; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40003-volatile-1.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40003-volatile-1.d new file mode 100644 index 00000000..2ef2634d --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40003-volatile-1.d @@ -0,0 +1,10 @@ +{ + while (a) + { + volatile if (b) + { + b--; + break; + } + } +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40004-volatile-2.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40004-volatile-2.d new file mode 100644 index 00000000..bc5a0de4 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40004-volatile-2.d @@ -0,0 +1,8 @@ +{ + if (e) + volatile + { + a++; + } + return oldValue; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40005-volatile-3.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40005-volatile-3.d new file mode 100644 index 00000000..039f788a --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40005-volatile-3.d @@ -0,0 +1,7 @@ +{ + if (e) + { + if (!value) + volatile e.value = value; + } +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40006-Lexer.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40006-Lexer.d new file mode 100644 index 00000000..86e1144a --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40006-Lexer.d @@ -0,0 +1,2472 @@ +/+
+ Copyright (c) 1999-2006 by Digital Mars
+ All Rights Reserved
+ written by Walter Bright www.digitalmars.com
+ License for redistribution is by either the Artistic License in artistic.txt, or the GNU General Public License in gnu.txt.
+ See the included readme.txt for details.
+ D Language conversion by: J Duncan
+ +/
+
+/**
+ d language lexer
+ */
+
+module dparser.Lexer;
+
+import dparser.Root;
+
+import dparser.Tokens;
+import dparser.Token;
+import dparser.Keyword;
+
+import dparser.Types;
+
+import dparser.Module;
+import dparser.Identifier;
+import dparser.unialpha;
+
+import dparser.OutBuffer;
+
+//private import std.ctype;
+//private import std.string;
+//import dwf.core.debugapi;
+
+int errno = 0;
+
+//#if _WIN32 && __DMC__
+// from \dm\src\include\setlocal.h
+//extern "C" char * __cdecl __locale_decpoint;
+char *__locale_decpoint;
+//#endif
+//const uint LS = 0x2028; // UTF line separator
+//const uint PS = 0x2029; // UTF paragraph separator
+
+//extern int isUniAlpha(unsigned u);
+//extern int HtmlNamedEntity(unsigned char *p, int length);
+
+/**
+ Lexer object
+ */
+
+class Lexer
+{
+ static Identifier[char[]] stringtable;
+ static OutBuffer stringbuffer;
+ static Token *freelist;
+
+ Token token; // current token
+ Module mod; // current module
+ Loc loc; // for error messages
+ ubyte *base; // pointer to start of buffer
+ ubyte *end; // past end of buffer
+ ubyte *p; // current character
+ int doDocComment; // collect doc comment information
+ int anyToken; // !=0 means seen at least one token
+ int commentToken; // !=0 means comments are TOKcomment's
+
+
+ this(Module mod, ubyte *base, uint begoffset, uint endoffset, int doDocComment, int commentToken)
+ {
+ if (stringbuffer is null)
+ stringbuffer = new OutBuffer;
+ loc = Loc(mod, 1);
+
+ this.base = base;
+ this.end = base + endoffset;
+ this.p = base + begoffset;
+ this.mod = mod;
+ this.doDocComment = doDocComment;
+ this.commentToken = commentToken;
+
+ /*
+ If first line starts with '#!', ignore the line
+ */
+
+ if (p[0] == '#' && p[1] == '!')
+ {
+ p += 2;
+ while (true)
+ {
+ ubyte c = *p;
+ switch (c)
+ {
+ case '\n':
+ p++;
+ break;
+
+ case '\r':
+ p++;
+ if (*p == '\n')
+ p++;
+ break;
+
+ case 0:
+ case 0x1A:
+ break;
+
+ default:
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ break;
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+
+ loc.linnum = 2;
+ }
+ }
+
+
+
+ // generate a unique identifier for this string
+ static Identifier idPool(in char[] str)
+ {
+// StringValue sv;
+// uint len = s.length;
+// StringValue sv = stringtable.update(s, len);
+// Identifier* id = cast(Identifier*) sv.ptrvalue;
+// if( id is null )
+ if ((str in stringtable) == null)
+ {
+ stringtable[str] = new Identifier(str, TOK.TOKidentifier);
+ }
+ return stringtable[str];
+ }
+
+ static void initKeywords()
+ {
+ // build character map
+ cmtable_init();
+
+ // create keyword tokens & identifiers
+ dparser.Keyword.initKeywords();
+
+ // create standard lexer tokens
+ dparser.Token.createLexerTokens();
+ }
+
+ // Combine two document comments into one.
+ static char[] combineComments(char[] c1, char[] c2)
+ {
+ char[] c = c2;
+ if (c1.length)
+ {
+ c = c1;
+ if (c2.length)
+ {
+ c = c1 ~ "\n" ~ c2;
+ }
+ }
+ return c;
+ }
+
+ // Decode UTF character. Issue error messages for invalid sequences. Return decoded character, advance p to last character in UTF sequence.
+ //! fix
+ uint decodeUTF()
+ {
+ ubyte *s = p;
+ ubyte c = *s;
+
+ assert(c & 0x80);
+ if (!(c & 0x80))
+ return c;
+
+ return cast(uint)'X';
+ /*
+ dchar u;
+ uint len;
+
+
+
+ // Check length of remaining string up to 6 UTF-8 characters
+ for( len = 1; len < 6 && s[len]; len++ )
+ {
+
+ }
+ /+
+ uint idx = 0;
+ char* msg = utf_decodeChar( s, len, &idx, &u );
+ p += idx - 1;
+ if( msg )
+ {
+ error(msg);
+ }
+ +/
+ return u;
+ */
+ }
+
+ void error(...)
+ {
+ if ((mod !is null) && !global.gag)
+ {
+ writefln(formatLoc(loc, _arguments, _argptr));
+ /*
+ char[] p = loc.toChars();
+ if( p.length )
+ writef( "%s: ", p );
+ writefx( stdout, _arguments, _argptr, 1 );
+ */
+ if (global.errors >= global.max_errors) // moderate blizzard of cascading messages
+ throw new Exception("too many errors");
+ }
+
+ global.errors++;
+ }
+
+ void errorLoc(Loc loc, ...)
+ {
+ if ((mod !is null) && !global.gag)
+ {
+ writefln(formatLoc(loc, _arguments, _argptr));
+ /*
+ char[] p = loc.toChars();
+ if( p.length )
+ writef("%s: ", p);
+ writefx(stdout, _arguments, _argptr, 1);
+ */
+ if (global.errors >= 20) // moderate blizzard of cascading messages
+ throw new Exception("too many errors");
+ }
+
+ global.errors++;
+ }
+
+
+ TOK nextToken()
+ {
+ if (token.next)
+ {
+ Token *t = token.next;
+ memcpy(&token, t, Token.sizeof);
+// t.next = freelist;
+// freelist = t;
+ }
+ else
+ {
+ scan(&token);
+ }
+// token.print();
+ return token.value;
+ }
+
+ Token *peek(inout Token ct)
+ {
+ Token *t;
+
+ if (ct.next)
+ t = ct.next;
+ else
+ {
+ t = new Token;
+ scan(t);
+ t.next = null;
+ ct.next = t;
+ }
+ return t;
+ }
+
+ // Turn next token in buffer into a token.
+
+ void scan(Token *t)
+ {
+// debug writefln("scan token");
+ uint lastLine = loc.linnum;
+ uint linnum;
+
+ t.blockComment = null;
+ t.lineComment = null;
+ while (true)
+ {
+ t.ptr = p;
+// debug writefln( " p = %d, *p = ", cast(uint)p, cast(char)*p );
+ switch (*p)
+ {
+ case 0:
+ case 0x1a:
+ t.value = TOK.TOKeof; // end of file
+// debug writefln( " EOF" );
+ return;
+
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ p++;
+// debug writefln( " whitespace" );
+ continue; // skip white space
+
+ case '\r':
+// debug writefln( " cr" );
+ p++;
+ if (*p != '\n') // if CR stands by itself
+ loc.linnum++;
+ continue; // skip white space
+
+ case '\n':
+// debug writefln( " nl" );
+ p++;
+ loc.linnum++;
+ continue; // skip white space
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ t.value = number(t);
+ return;
+
+/*
+ #if CSTRINGS
+ case '\'':
+ t.value = charConstant(t, 0);
+ return;
+
+ case '"':
+ t.value = stringConstant(t,0);
+ return;
+
+ case 'l':
+ case 'L':
+ if( p[1] == '\'')
+ {
+ p++;
+ t.value = charConstant(t, 1);
+ return;
+ }
+ else if( p[1] == '"')
+ {
+ p++;
+ t.value = stringConstant(t, 1);
+ return;
+ }
+ #else
+ */
+ case '\'':
+// debug writefln( " char" );
+ t.value = charConstant(t, 0);
+ return;
+
+ case 'r':
+// debug writefln( " wysiwyg" );
+ if (p[1] != '"')
+ goto case_identifier;
+ p++;
+
+ case '`':
+ t.value = wysiwygStringConstant(t, *p);
+ return;
+
+ case 'x':
+// debug writefln( " hex string" );
+ if (p[1] != '"')
+ goto case_identifier;
+ p++;
+ t.value = hexStringConstant(t);
+ return;
+
+
+ case '"':
+// debug writefln( " string" );
+ t.value = escapeStringConstant(t, 0);
+// debug writefln( t.ustring );
+ return;
+
+ case '\\': // escaped string literal
+// debug writefln( " escaped string literal" );
+ uint c;
+ stringbuffer.offset = 0;
+ do
+ {
+ p++;
+ c = escapeSequence();
+ stringbuffer.write(c);
+ } while (*p == '\\');
+// t.len = stringbuffer.offset;
+// stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// memcpy( t.ustring.ptr, stringbuffer.data, stringbuffer.offset );
+ t.postfix = 0;
+ t.value = TOK.TOKstring;
+ return;
+
+ case 'l':
+ case 'L':
+// #endif
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q': /*case 'r':*/
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w': /*case 'x':*/
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case_identifier:
+ {
+// debug writefln( " identifier" );
+ ubyte c;
+ do
+ {
+ c = *++p;
+ } while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
+
+// sv = stringtable.update((char *)t.ptr, p - t.ptr);
+ char[] tmp;
+ tmp.length = p - t.ptr;
+ memcpy(tmp.ptr, t.ptr, p - t.ptr);
+ Identifier id;
+ Identifier *pid = tmp in stringtable;
+ if (pid)
+ {
+ id = *pid;
+ }
+
+ if (id is null)
+ {
+ id = new Identifier(tmp, TOK.TOKidentifier);
+ stringtable[tmp] = id;
+ }
+
+ t.identifier = id;
+ t.value = cast(TOK)id.value;
+ anyToken = 1;
+
+ // if special identifier token
+ if (*t.ptr == '_')
+ {
+ static char date[11 + 1];
+ static char time[8 + 1];
+ static char timestamp[24 + 1];
+
+ if (!date[0]) // lazy evaluation
+ {
+ //!!
+ /+
+ time_t t;
+ char *p;
+ .time(&t);
+ p = ctime(&t);
+ assert(p);
+ sprintf(date.ptr, "%.6s %.4s", p + 4, p + 20);
+ sprintf(time.ptr, "%.8s", p + 11);
+ sprintf(timestamp.ptr, "%.24s", p);
+ +/
+ }
+
+ if (mod && id is Id.FILE)
+ {
+ t.value = TOK.TOKstring;
+ if (loc.filename.length)
+ t.ustring = loc.filename;
+ else
+ t.ustring = mod.identifier.toChars();
+ goto Llen;
+ }
+ else if (mod && id == Id.LINE)
+ {
+ t.value = TOK.TOKint64v;
+ t.uns64value = loc.linnum;
+ }
+ else if (id == Id.DATE)
+ {
+ t.value = TOK.TOKstring;
+ //! t.ustring = date;
+ goto Llen;
+ }
+ else if (id == Id.TIME)
+ {
+ t.value = TOK.TOKstring;
+ //! t.ustring = time;
+ goto Llen;
+ }
+ else if (id == Id.TIMESTAMP)
+ {
+ t.value = TOK.TOKstring;
+ //! t.ustring = timestamp;
+ Llen:
+ t.postfix = 0;
+// t.len = strlen((char *)t.ustring);
+ }
+ }
+ //printf("t.value = %d\n",t.value);
+ return;
+ }
+
+ // comments
+ case '/':
+ p++;
+ switch (*p)
+ {
+ case '=':
+ p++;
+ t.value = TOK.TOKdivass;
+ return;
+
+ case '*': // '/*'
+ p++;
+ linnum = loc.linnum;
+ while (true)
+ {
+ while (true)
+ {
+ ubyte c = *p;
+ switch (c)
+ {
+ case '/':
+ break;
+
+ case '\n':
+ loc.linnum++;
+ p++;
+ continue;
+
+ case '\r':
+ p++;
+ if (*p != '\n')
+ loc.linnum++;
+ continue;
+
+ case 0:
+ case 0x1A:
+ error("unterminated /* */ comment");
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ loc.linnum++;
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+ p++;
+ if (p[-2] == '*' && p - 3 != t.ptr)
+ break;
+ }
+
+ if (commentToken)
+ {
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ // if /** but not /**/
+ else if (doDocComment && t.ptr[2] == '*' && p - 4 != t.ptr)
+ getDocComment(t, lastLine == linnum); //! ?
+ continue;
+
+ case '/': // do // style comments
+ linnum = loc.linnum;
+ while (1)
+ {
+ ubyte c = *++p;
+ switch (c)
+ {
+ case '\n':
+ break;
+
+ case '\r':
+ if (p[1] == '\n')
+ p++;
+ break;
+
+ case 0:
+ case 0x1a:
+ if (commentToken)
+ {
+ p = end;
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '/')
+ getDocComment(t, lastLine == linnum);
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ break;
+ }
+ continue;
+ }
+ break;
+ }
+
+ if (commentToken)
+ {
+ p++;
+ loc.linnum++;
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '/')
+ getDocComment(t, lastLine == linnum);
+
+ p++;
+ loc.linnum++;
+ continue;
+
+ case '+':
+ {
+ int nest;
+ linnum = loc.linnum;
+ p++;
+ nest = 1;
+ while (1)
+ {
+ ubyte c = *p;
+ switch (c)
+ {
+ case '/':
+ p++;
+ if (*p == '+')
+ {
+ p++;
+ nest++;
+ }
+ continue;
+
+ case '+':
+ p++;
+ if (*p == '/')
+ {
+ p++;
+ if (--nest == 0)
+ break;
+ }
+ continue;
+
+ case '\r':
+ p++;
+ if (*p != '\n')
+ loc.linnum++;
+ continue;
+
+ case '\n':
+ loc.linnum++;
+ p++;
+ continue;
+
+ case 0:
+ case 0x1A:
+ error("unterminated /+ +/ comment");
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ loc.linnum++;
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+ if (commentToken)
+ {
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '+' && p - 4 != t.ptr)
+ {
+ // if /++ but not /++/
+ getDocComment(t, lastLine == linnum);
+ }
+ continue;
+ }
+
+ default:
+ break;
+ }
+ t.value = TOK.TOKdiv;
+ return;
+
+ case '.':
+ p++;
+ if (isdigit(*p))
+ {
+ p--;
+ t.value = inreal(t);
+ }
+ else if (p[0] == '.')
+ {
+ if (p[1] == '.')
+ {
+ p += 2;
+ t.value = TOK.TOKdotdotdot;
+ }
+ else
+ {
+ p++;
+ t.value = TOK.TOKslice;
+ }
+ }
+ else
+ t.value = TOK.TOKdot;
+ return;
+
+ case '&':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKandass;
+ }
+ else if (*p == '&')
+ {
+ p++;
+ t.value = TOK.TOKandand;
+ }
+ else
+ t.value = TOK.TOKand;
+ return;
+
+ // |, ||, |=
+ case '|':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKorass;
+ }
+ else if (*p == '|')
+ {
+ p++;
+ t.value = TOK.TOKoror;
+ }
+ else
+ t.value = TOK.TOKor;
+ return;
+
+ case '-':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKminass;
+ }
+ else if (*p == '-')
+ {
+ p++;
+ t.value = TOK.TOKminusminus;
+ }
+ else
+ t.value = TOK.TOKmin;
+ return;
+
+ // +, +=, ++
+ case '+':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKaddass; // +=
+ }
+ else if (*p == '+')
+ {
+ p++;
+ t.value = TOK.TOKplusplus; // ++
+ }
+ else
+ t.value = TOK.TOKadd; // +
+ return;
+
+ // <, <=, <<=, <<, <>=, <>
+ case '<':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKle; // <=
+ }
+ else if (*p == '<')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKshlass; // <<=
+ }
+ else
+ t.value = TOK.TOKshl; // <<
+ }
+ else if (*p == '>')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKleg; // <>=
+ }
+ else
+ t.value = TOK.TOKlg; // <>
+ }
+ else
+ t.value = TOK.TOKlt; // <
+ return;
+
+ // >, >>, >>>, >=, >>=, >>>=
+ case '>':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKge; // >=
+ }
+ else if (*p == '>')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKshrass; // >>=
+ }
+ else if (*p == '>')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKushrass; // >>>=
+ }
+ else
+ t.value = TOK.TOKushr; // >>>
+ }
+ else
+ t.value = TOK.TOKshr; // >>
+ }
+ else
+ t.value = TOK.TOKgt; // >
+ return;
+
+ case '!':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKnotidentity; // !==
+ }
+ else
+ t.value = TOK.TOKnotequal; // !=
+ }
+ else if (*p == '<')
+ {
+ p++;
+ if (*p == '>')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKunord; // !<>=
+ }
+ else
+ t.value = TOK.TOKue; // !<>
+ }
+ else if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKug; // !<=
+ }
+ else
+ t.value = TOK.TOKuge; // !<
+ }
+ else if (*p == '>')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKul; // !>=
+ }
+ else
+ t.value = TOK.TOKule; // !>
+ }
+ else
+ t.value = TOK.TOKnot; // !
+ return;
+
+ case '=':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKidentity; // ===
+ }
+ else
+ t.value = TOK.TOKequal; // ==
+ }
+ else
+ t.value = TOK.TOKassign; // =
+ return;
+
+ case '~':
+ p++;
+ if (*p == '=')
+ {
+ p++;
+ t.value = TOK.TOKcatass; // ~=
+ }
+ else
+ t.value = TOK.TOKtilde; // ~
+ return;
+
+ // SINGLE
+ case '(': p++; t.value = TOK.TOKlparen; return;
+
+ case ')': p++; t.value = TOK.TOKrparen; return;
+
+ case '[': p++; t.value = TOK.TOKlbracket; return;
+
+ case ']': p++; t.value = TOK.TOKrbracket; return;
+
+ case '{': p++; t.value = TOK.TOKlcurly; return;
+
+ case '}': p++; t.value = TOK.TOKrcurly; return;
+
+ case '?': p++; t.value = TOK.TOKquestion; return;
+
+ case ',': p++; t.value = TOK.TOKcomma; return;
+
+ case ';': p++; t.value = TOK.TOKsemicolon; return;
+
+ case ':': p++; t.value = TOK.TOKcolon; return;
+
+ case '$': p++; t.value = TOK.TOKdollar; return;
+
+ // DOUBLE
+ case '*': p++; if (*p == '=')
+ {
+ p++; t.value = TOK.TOKmulass;
+ }
+ else
+ t.value = TOK.TOKmul;
+ return;
+
+ case '%': p++; if (*p == '=')
+ {
+ p++; t.value = TOK.TOKmodass;
+ }
+ else
+ t.value = TOK.TOKmod;
+ return;
+
+ case '^': p++; if (*p == '=')
+ {
+ p++; t.value = TOK.TOKxorass;
+ }
+ else
+ t.value = TOK.TOKxor;
+ return;
+
+// removed 148 case '~': p++; if( *p == '=' ) { p++; t.value = TOK.TOKcatass; } else t.value = TOK.TOKtilde; return;
+
+
+ case '#':
+ p++;
+ Pragma();
+ continue;
+
+ default:
+ {
+ debug writefln(" default char");
+ ubyte c = *p;
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ // Check for start of unicode identifier
+ if (isUniAlpha(u))
+ goto case_identifier;
+
+ if (u == PS || u == LS)
+ {
+ loc.linnum++;
+ p++;
+ continue;
+ }
+ }
+ if (isprint(c))
+ error("unsupported char '%s'", cast(char)c);
+ else
+ error("unsupported char 0x%02x", cast(ubyte)c);
+ p++;
+ continue;
+ }
+ }
+ }
+ }
+
+
+
+ // Parse escape sequence.
+ uint escapeSequence()
+ {
+ uint c;
+ int n;
+ int ndigits;
+
+ c = *p;
+ switch (c)
+ {
+ case '\'':
+ case '"':
+ case '?':
+ case '\\':
+ Lconsume:
+ p++;
+ break;
+
+ case 'a': c = 7; goto Lconsume;
+
+ case 'b': c = 8; goto Lconsume;
+
+ case 'f': c = 12; goto Lconsume;
+
+ case 'n': c = 10; goto Lconsume;
+
+ case 'r': c = 13; goto Lconsume;
+
+ case 't': c = 9; goto Lconsume;
+
+ case 'v': c = 11; goto Lconsume;
+
+ case 'u':
+ ndigits = 4;
+ goto Lhex;
+
+ case 'U':
+ ndigits = 8;
+ goto Lhex;
+
+ case 'x':
+ ndigits = 2;
+ Lhex:
+ p++;
+ c = *p;
+ if (ishex(c))
+ {
+ uint v;
+ n = 0;
+ v = 0;
+ while (1)
+ {
+ if (isdigit(c))
+ c -= '0';
+ else if (islower(c))
+ c -= 'a' - 10;
+ else
+ c -= 'A' - 10;
+ v = v * 16 + c;
+ c = *++p;
+ if (++n == ndigits)
+ break;
+ if (!ishex(c))
+ {
+ error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
+ break;
+ }
+ }
+//! if( ndigits != 2 && !utf_isValidDchar(v))
+//! error("invalid UTF character \\U%08x", v);
+ c = v;
+ }
+ else
+ error("undefined escape hex sequence \\%s\n", c);
+ break;
+
+ case '&': // named character entity
+ for (ubyte *idstart = ++p; 1; p++)
+ {
+ switch (*p)
+ {
+ case ';':
+ //!!!
+ /+
+ c = HtmlNamedEntity(idstart, p - idstart);
+ if( c == ~0 )
+ {
+ error("unnamed character entity &%.*s;", p - idstart, idstart);
+ c = ' ';
+ }
+
+ p++;
+ +/
+ break;
+
+ default:
+ if (isalpha(*p) || (p != idstart + 1 && isdigit(*p)))
+ continue;
+ error("unterminated named entity");
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0:
+ case 0x1a: // end of file
+ c = '\\';
+ break;
+
+ default:
+ if (isoctal(c))
+ {
+ ubyte v;
+ n = 0;
+ do
+ {
+ v = v * 8 + (c - '0');
+ c = *++p;
+ } while (++n < 3 && isoctal(c));
+ c = v;
+ }
+ else
+ error("undefined escape sequence \\%s\n", c);
+ break;
+ }
+ return c;
+ }
+
+ /**************************************
+ */
+
+ TOK wysiwygStringConstant(Token *t, int tc)
+ {
+ uint c;
+ Loc start = loc;
+
+ p++;
+ stringbuffer.offset = 0;
+ while (1)
+ {
+ c = *p++;
+ switch (c)
+ {
+ case '\n':
+ loc.linnum++;
+ break;
+
+ case '\r':
+ if (*p == '\n')
+ continue; // ignore
+ c = '\n'; // treat EndOfLine as \n character
+ loc.linnum++;
+ break;
+
+ case 0:
+ case 0x1a:
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+ t.postfix = 0;
+ return TOK.TOKstring;
+
+ case '"':
+ case '`':
+ if (c == tc)
+ {
+// t.len = stringbuffer.offset;
+ stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+// memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+ return TOK.TOKstring;
+ }
+ break;
+
+ default:
+ if (c & 0x80)
+ {
+ p--;
+ uint u = decodeUTF();
+ p++;
+ if (u == PS || u == LS)
+ loc.linnum++;
+ stringbuffer.write(u);
+ continue;
+ }
+ break;
+ }
+ stringbuffer.write(c);
+ }
+ }
+
+ /**************************************
+ * Lex hex strings:
+ * x"0A ae 34FE BD"
+ */
+
+ TOK hexStringConstant(Token *t)
+ {
+ uint c;
+ Loc start = loc;
+ uint n = 0;
+ uint v;
+
+ p++;
+ stringbuffer.offset = 0;
+ while (1)
+ {
+ c = *p++;
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ continue; // skip white space
+
+ case '\r':
+ if (*p == '\n')
+ continue; // ignore
+
+ // Treat isolated '\r' as if it were a '\n'
+ case '\n':
+ loc.linnum++;
+ continue;
+
+ case 0:
+ case 0x1a:
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+ t.postfix = 0;
+ return TOK.TOKstring;
+
+ case '"':
+ if (n & 1)
+ {
+ error("odd number (%d) of hex characters in hex string", n);
+ stringbuffer.write(v);
+ }
+// t.len = stringbuffer.offset;
+// stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+// memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+ return TOK.TOKstring;
+
+ default:
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'A' - 10;
+ else if (c & 0x80)
+ {
+ p--;
+ uint u = decodeUTF();
+ p++;
+ if (u == PS || u == LS)
+ loc.linnum++;
+ else
+ error("non-hex character \\u%x", u);
+ }
+ else
+ error("non-hex character '%s'", c);
+ if (n & 1)
+ {
+ v = (v << 4) | c;
+ stringbuffer.write(v);
+ }
+ else
+ v = c;
+ n++;
+ break;
+ }
+ }
+ }
+
+ /**************************************
+ */
+
+ TOK escapeStringConstant(Token *t, int wide)
+ {
+ uint c;
+ Loc start = loc;
+
+ p++;
+ stringbuffer.offset = 0;
+ // debug writefln( "escape string constant: %s", std.string.toString( cast(char*)p ) );
+ while (1)
+ {
+ c = *p++;
+ switch (c)
+ {
+ case '\\':
+ switch (*p)
+ {
+ case 'u':
+ case 'U':
+ case '&':
+ c = escapeSequence();
+ stringbuffer.write(c);
+ continue;
+
+ default:
+ c = escapeSequence();
+ break;
+ }
+ break;
+
+ case '\n':
+ loc.linnum++;
+ break;
+
+ case '\r':
+ if (*p == '\n')
+ continue; // ignore
+ c = '\n'; // treat EndOfLine as \n character
+ loc.linnum++;
+ break;
+
+ case '"':
+// writefln( "end of string: ", stringbuffer.toString );
+ t.ustring = stringbuffer.toString().dup;
+ // t.len = stringbuffer.offset;
+ // stringbuffer.write(cast(byte)0);
+ // t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+ // memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+
+ return TOK.TOKstring;
+
+ case 0:
+ case 0x1a:
+ p--;
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+// t.len = 0;
+ t.postfix = 0;
+ return TOK.TOKstring;
+
+ default:
+ if (c & 0x80)
+ {
+ p--;
+ c = decodeUTF();
+ if (c == LS || c == PS)
+ {
+ c = '\n';
+ loc.linnum++;
+ }
+ p++;
+ stringbuffer.write(cast(char)c);
+ continue;
+ }
+ break;
+ }
+ stringbuffer.write(cast(char)c);
+// writefln( stringbuffer.toString );
+ }
+ }
+
+ //**************************************
+ TOK charConstant(Token *t, int wide)
+ {
+ uint c;
+ TOK tk = TOK.TOKcharv;
+
+ //printf("Lexer.charConstant\n");
+ p++;
+ c = *p++;
+ switch (c)
+ {
+ case '\\':
+ switch (*p)
+ {
+ case 'u':
+ t.uns64value = escapeSequence();
+ tk = TOK.TOKwcharv;
+ break;
+
+ case 'U':
+ case '&':
+ t.uns64value = escapeSequence();
+ tk = TOK.TOKdcharv;
+ break;
+
+ default:
+ t.uns64value = escapeSequence();
+ break;
+ }
+ break;
+
+ case '\n':
+ L1:
+ loc.linnum++;
+
+ case '\r':
+ case 0:
+ case 0x1a:
+ case '\'':
+ error("unterminated character constant");
+ return tk;
+
+ default:
+ if (c & 0x80)
+ {
+ p--;
+ c = decodeUTF();
+ p++;
+ if (c == LS || c == PS)
+ goto L1;
+ if (c < 0xd800 || (c >= 0xe000 && c < 0xfffe))
+ tk = TOK.TOKwcharv;
+ else
+ tk = TOK.TOKdcharv;
+ }
+ t.uns64value = c;
+ break;
+ }
+
+ if (*p != '\'')
+ {
+ error("unterminated character constant");
+ return tk;
+ }
+ p++;
+ return tk;
+ }
+
+ // Get postfix of string literal.
+ void stringPostfix(Token *t)
+ {
+ switch (*p)
+ {
+ case 'c':
+ case 'w':
+ case 'd':
+ t.postfix = *p;
+ p++;
+ break;
+
+ default:
+ t.postfix = 0;
+ break;
+ }
+ }
+
+ /***************************************
+ * Read \u or \U unicode sequence
+ * Input:
+ * u 'u' or 'U'
+ */
+ /*
+ uint Wchar(uint u)
+ {
+ uint value;
+ uint n;
+ ubyte c;
+ uint nchars;
+
+ nchars = (u == 'U') ? 8 : 4;
+ value = 0;
+ for (n = 0; 1; n++)
+ {
+ ++p;
+ if( n == nchars)
+ break;
+ c = *p;
+ if( !ishex(c))
+ {
+ error("\\%s sequence must be followed by %d hex characters", u, nchars);
+ break;
+ }
+ if( isdigit(c))
+ c -= '0';
+ else if( islower(c))
+ c -= 'a' - 10;
+ else
+ c -= 'A' - 10;
+ value <<= 4;
+ value |= c;
+ }
+ return value;
+ }
+ */
+
+ /**************************************
+ * Read in a number.
+ * If it's an integer, store it in tok.TKutok.Vlong.
+ * integers can be decimal, octal or hex
+ * Handle the suffixes U, UL, LU, L, etc.
+ * If it's double, store it in tok.TKutok.Vdouble.
+ * Returns:
+ * TKnum
+ * TKdouble,...
+ */
+
+ TOK number(Token *t)
+ {
+ //debug writefln("Lexer.number()");
+ // We use a state machine to collect numbers
+ enum STATE
+ {
+ STATE_initial,
+ STATE_0,
+ STATE_decimal,
+ STATE_octal,
+ STATE_octale,
+ STATE_hex,
+ STATE_binary,
+ STATE_hex0,
+ STATE_binary0,
+ STATE_hexh,
+ STATE_error
+ }
+
+ enum FLAGS
+ {
+ FLAGS_decimal = 1, // decimal
+ FLAGS_unsigned = 2, // u or U suffix
+ FLAGS_long = 4, // l or L suffix
+ }
+ FLAGS flags = FLAGS.FLAGS_decimal;
+
+ int i;
+ TOK result;
+ int base;
+
+ stringbuffer.offset = 0;
+// stringbuffer.data = null;
+ STATE state = STATE.STATE_initial;
+ ubyte *start = p;
+
+ TOK _isreal()
+ {
+ p = start;
+ return inreal(t);
+ }
+
+ while (true)
+ {
+ char c = cast(char)*p;
+ switch (state)
+ {
+ case STATE.STATE_initial: // opening state
+ if (c == '0')
+ state = STATE.STATE_0;
+ else
+ state = STATE.STATE_decimal;
+ break;
+
+ case STATE.STATE_0:
+ flags = cast(FLAGS)(flags & ~FLAGS.FLAGS_decimal);
+ switch (c)
+ {
+ // #if ZEROH
+// case 'H': // 0h
+// case 'h':
+// goto hexh;
+ // #endif
+ case 'X':
+ case 'x':
+ state = STATE.STATE_hex0;
+ break;
+
+ case '.':
+ if (p[1] == '.') // .. is a separate token
+ goto done;
+
+ case 'i':
+ case 'f':
+ case 'F':
+ goto _Real;
+
+ // #if ZEROH
+// case 'E':
+// case 'e':
+// goto case_hex;
+ // #endif
+ case 'B':
+ case 'b':
+ state = STATE.STATE_binary0;
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ state = STATE.STATE_octal;
+ break;
+
+ // #if ZEROH
+// case '8': case '9': case 'A':
+// case 'C': case 'D': case 'F':
+// case 'a': case 'c': case 'd': case 'f':
+// case_hex:
+// state = STATE.STATE_hexh;
+// break;
+ // #endif
+ case '_':
+ state = STATE.STATE_octal;
+ p++;
+ continue;
+
+ default:
+ goto done;
+ }
+ break;
+
+ case STATE.STATE_decimal: // reading decimal number
+
+ // if its not a digit - decimal complete or not a decimal
+ if (!isdigit(c))
+ {
+// debug writefln( "\tnon-digit( %s )", c );
+ // #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+ // #endif
+ //! wtf ?
+ // ignore embedded _
+ if (c == '_')
+ {
+ p++;
+ continue;
+ }
+
+ // check decimal point - make real
+ if (c == '.' && p[1] != '.')
+ goto _Real;
+
+ // check for mantra - make real
+ if (c == 'i' || c == 'f' || c == 'F' || c == 'e' || c == 'E')
+ {
+ _Real: // It's a real number. Back up and rescan as a real
+ p = start;
+ return inreal(t);
+ }
+
+ goto done;
+ }
+ break;
+
+ case STATE.STATE_hex0: // reading hex number
+ case STATE.STATE_hex:
+ if (!ishex(c))
+ {
+ if (c == '_') // ignore embedded _
+ {
+ p++;
+ continue;
+ }
+ if (c == '.' && p[1] != '.')
+ goto _Real;
+ if (c == 'P' || c == 'p' || c == 'i')
+ goto _Real;
+ if (state == STATE.STATE_hex0)
+ error("Hex digit expected, not '%s'", c);
+ goto done;
+ }
+ state = STATE.STATE_hex;
+ break;
+
+ // #if ZEROH
+// hexh:
+// state = STATE.STATE_hexh;
+//
+// case STATE.STATE_hexh: // parse numbers like 0FFh
+// if( !ishex(c))
+// {
+// if( c == 'H' || c == 'h')
+// {
+// p++;
+// base = 16;
+// goto done;
+// }
+// else
+// {
+// // Check for something like 1E3 or 0E24
+// if( memchr(stringbuffer.data.ptr, 'E', stringbuffer.offset) || memchr( stringbuffer.data.ptr, 'e', stringbuffer.offset))
+// goto _Real;
+// error("Hex digit expected, not '%s'", c);
+// goto done;
+// }
+// }
+// break;
+ // #endif
+
+ case STATE.STATE_octal: // reading octal number
+ case STATE.STATE_octale: // reading octal number with non-octal digits
+ if (!isoctal(c))
+ {
+// #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+// #endif
+ if (c == '_') // ignore embedded _
+ {
+ p++;
+ continue;
+ }
+ if (c == '.' && p[1] != '.')
+ goto _Real;
+ if (c == 'i')
+ goto _Real;
+ if (isdigit(c))
+ state = STATE.STATE_octale;
+ else
+ goto done;
+ }
+ break;
+
+ case STATE.STATE_binary0: // starting binary number
+ case STATE.STATE_binary: // reading binary number
+ if (c != '0' && c != '1')
+ {
+ // #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+ // #endif
+ if (c == '_') // ignore embedded _
+ {
+ p++;
+ continue;
+ }
+ if (state == STATE.STATE_binary0)
+ {
+ error("binary digit expected");
+ state = STATE.STATE_error;
+ break;
+ }
+ else
+ goto done;
+ }
+ state = STATE.STATE_binary;
+ break;
+
+ case STATE.STATE_error: // for error recovery
+ if (!isdigit(c)) // scan until non-digit
+ goto done;
+ break;
+
+ default:
+ assert(0);
+ }
+ stringbuffer.write(cast(char)c);
+ p++;
+ }
+ done:
+ stringbuffer.write(cast(char)0); // terminate string
+
+// debug writefln( "\tdigit complete( %s )", stringbuffer.toString );
+
+ if (state == STATE.STATE_octale)
+ error("Octal digit expected");
+
+ uinteger_t n; // unsigned >=64 bit integer type
+
+ if (stringbuffer.offset == 2 && (state == STATE.STATE_decimal || state == STATE.STATE_0))
+ n = stringbuffer.data[0] - '0';
+ else
+ {
+ // Convert string to integer
+ char *p = cast(char *)stringbuffer.data.ptr;
+ int r = 10;
+ int d;
+ if (*p == '0')
+ {
+ if (p[1] == 'x' || p[1] == 'X')
+ {
+ // "0x#"
+ p += 2;
+ r = 16;
+ }
+ else if (p[1] == 'b' || p[1] == 'B')
+ {
+ // "0b#" - binary
+ p += 2;
+ r = 2;
+ }
+ else if (isdigit(p[1]))
+ {
+ p += 1;
+ r = 8;
+ }
+ }
+
+ n = 0;
+
+ while (true)
+ {
+ if (*p >= '0' && *p <= '9')
+ d = *p - '0';
+ else if (*p >= 'a' && *p <= 'z')
+ d = *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'Z')
+ d = *p - 'A' + 10;
+ else
+ break;
+
+ if (d >= r)
+ break;
+
+ if (n * r + d < n)
+ {
+ error("integer overflow");
+ break;
+ }
+
+ n = n * r + d;
+ p++;
+ }
+
+ // if n needs more than 64 bits
+ if (n.sizeof > 8 && n > 0xffffffffffffffffL)
+ error("integer overflow");
+ }
+
+ // Parse trailing 'u', 'U', 'l' or 'L' in any combination
+ while (true)
+ {
+ ubyte f;
+ switch (*p)
+ {
+ case 'U':
+ case 'u':
+ f = FLAGS.FLAGS_unsigned;
+ goto L1;
+
+ case 'L':
+ case 'l':
+ f = FLAGS.FLAGS_long;
+ L1:
+ p++;
+ if (flags & f)
+ error("unrecognized token");
+ flags = cast(FLAGS)(flags | f);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ switch (flags)
+ {
+ case 0:
+ /* Octal or Hexadecimal constant.
+ * First that fits: int, uint, long, ulong
+ */
+ if (n & 0x8000000000000000L)
+ result = TOK.TOKuns64v;
+ else if (n & 0xffffffff00000000L)
+ result = TOK.TOKint64v;
+ else if (n & 0x80000000)
+ result = TOK.TOKuns32v;
+ else
+ result = TOK.TOKint32v;
+ break;
+
+ case FLAGS.FLAGS_decimal:
+ /* First that fits: int, long, long long
+ */
+ if (n & 0x8000000000000000L)
+ {
+ error("signed integer overflow");
+ result = TOK.TOKuns64v;
+ }
+ else if (n & 0xffffffff80000000L)
+ result = TOK.TOKint64v;
+ else
+ result = TOK.TOKint32v;
+ break;
+
+ case FLAGS.FLAGS_unsigned:
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned:
+ /* First that fits: uint, ulong
+ */
+ if (n & 0xffffffff00000000L)
+ result = TOK.TOKuns64v;
+ else
+ result = TOK.TOKuns32v;
+ break;
+
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_long:
+ if (n & 0x8000000000000000L)
+ {
+ error("signed integer overflow");
+ result = TOK.TOKuns64v;
+ }
+ else
+ result = TOK.TOKint64v;
+ break;
+
+ case FLAGS.FLAGS_long:
+ if (n & 0x8000000000000000L)
+ result = TOK.TOKuns64v;
+ else
+ result = TOK.TOKint64v;
+ break;
+
+ case FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+ result = TOK.TOKuns64v;
+ break;
+
+ default:
+ debug writefln("%x", flags);
+ assert(0);
+ }
+ t.uns64value = n;
+ return result;
+ }
+
+ /**************************************
+ * Read in characters, converting them to real.
+ * Bugs:
+ * Exponent overflow not detected.
+ * Too much requested precision is not detected.
+ */
+
+ TOK inreal(Token *t)
+ {
+ int dblstate;
+ uint c;
+ char hex; // is this a hexadecimal-floating-constant?
+ TOK result;
+
+ //printf("Lexer.inreal()\n");
+ stringbuffer.offset = 0;
+ dblstate = 0;
+ hex = 0;
+ Lnext:
+ while (1)
+ {
+ // Get next char from input
+ c = *p++;
+ //printf("dblstate = %d, c = '%s'\n", dblstate, c);
+ while (1)
+ {
+ switch (dblstate)
+ {
+ case 0: // opening state
+ if (c == '0')
+ dblstate = 9;
+ else if (c == '.')
+ dblstate = 3;
+ else
+ dblstate = 1;
+ break;
+
+ case 9:
+ dblstate = 1;
+ if (c == 'X' || c == 'x')
+ {
+ hex++;
+ break;
+ }
+
+ case 1: // digits to left of .
+ case 3: // digits to right of .
+ case 7: // continuing exponent digits
+ if (!isdigit(c) && !(hex && isxdigit(c)))
+ {
+ if (c == '_')
+ goto Lnext; // ignore embedded '_'
+ dblstate++;
+ continue;
+ }
+ break;
+
+ case 2: // no more digits to left of .
+ if (c == '.')
+ {
+ dblstate++;
+ break;
+ }
+
+ case 4: // no more digits to right of .
+ if ((c == 'E' || c == 'e') || hex && (c == 'P' || c == 'p'))
+ {
+ dblstate = 5;
+ hex = 0; // exponent is always decimal
+ break;
+ }
+ if (hex)
+ error("binary-exponent-part required");
+ goto done;
+
+ case 5: // looking immediately to right of E
+ dblstate++;
+ if (c == '-' || c == '+')
+ break;
+
+ case 6: // 1st exponent digit expected
+ if (!isdigit(c))
+ error("exponent expected");
+ dblstate++;
+ break;
+
+ case 8: // past end of exponent digits
+ goto done;
+ }
+ break;
+ }
+ stringbuffer.write(c);
+ }
+ done:
+ p--;
+
+ stringbuffer.write(cast(byte)0);
+
+// #if _WIN32 && __DMC__
+ char *save = __locale_decpoint;
+
+ __locale_decpoint = ".";
+// #endif
+ t.float80value = strtold(cast(char *)stringbuffer.data.ptr, null);
+ errno = 0;
+ switch (*p)
+ {
+ case 'F':
+ case 'f':
+ strtof(cast(char *)stringbuffer.data.ptr, null);
+ result = TOK.TOKfloat32v;
+ p++;
+ break;
+
+ default:
+ strtod(cast(char *)stringbuffer.data.ptr, null);
+ result = TOK.TOKfloat64v;
+ break;
+
+ case 'L':
+ case 'l':
+ result = TOK.TOKfloat80v;
+ p++;
+ break;
+ }
+ if (*p == 'i' || *p == 'I')
+ {
+ p++;
+ switch (result)
+ {
+ case TOK.TOKfloat32v:
+ result = TOK.TOKimaginary32v;
+ break;
+
+ case TOK.TOKfloat64v:
+ result = TOK.TOKimaginary64v;
+ break;
+
+ case TOK.TOKfloat80v:
+ result = TOK.TOKimaginary80v;
+ break;
+ }
+ }
+// #if _WIN32 && __DMC__
+ __locale_decpoint = save;
+// #endif
+ if (errno == ERANGE)
+ error("number is not representable");
+ return result;
+ }
+
+
+
+
+ /*********************************************
+ * Do pragma.
+ * Currently, the only pragma supported is:
+ * #line linnum [filespec]
+ */
+
+ void Pragma()
+ {
+ Token tok;
+ int linnum;
+
+ char[] filespec;
+ Loc loc = this.loc;
+
+ scan(&tok);
+
+ if (tok.value != TOK.TOKidentifier || tok.identifier != Id.line)
+ goto Lerr;
+
+ scan(&tok);
+ if (tok.value == TOK.TOKint32v || tok.value == TOK.TOKint64v)
+ linnum = tok.uns64value - 1;
+ else
+ goto Lerr;
+
+ while (1)
+ {
+ switch (*p)
+ {
+ case 0:
+ case 0x1a:
+ case '\n':
+ Lnewline:
+ this.loc.linnum = linnum;
+ if (filespec.length)
+ this.loc.filename = filespec;
+ return;
+
+ case '\r':
+ p++;
+ if (*p != '\n')
+ {
+ p--;
+ goto Lnewline;
+ }
+ continue;
+
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ p++;
+ continue; // skip white space
+
+ case '_':
+ if (mod && memcmp(p, cast(char *)"__FILE__", 8) == 0)
+ {
+ p += 8;
+//! filespec = mem.strdup(loc.filename ? loc.filename : mod.identifier.toChars());
+ }
+ continue;
+
+ case '"':
+ if (filespec)
+ goto Lerr;
+ stringbuffer.offset = 0;
+ p++;
+ while (1)
+ {
+ uint c;
+ c = *p;
+ switch (c)
+ {
+ case '\n':
+ case '\r':
+ case 0:
+ case 0x1a:
+ goto Lerr;
+
+ case '"':
+ stringbuffer.write(cast(byte)0);
+ // filespec = mem.strdup((char *)stringbuffer.data);
+ filespec = stringbuffer.toString.dup;
+ p++;
+ break;
+
+ default:
+ if (c & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ goto Lerr;
+ }
+ stringbuffer.write(c);
+ p++;
+ continue;
+ }
+ break;
+ }
+ continue;
+
+ default:
+ if (*p & 0x80)
+ {
+ uint u = decodeUTF();
+ if (u == PS || u == LS)
+ goto Lnewline;
+ }
+ goto Lerr;
+ }
+ }
+
+ Lerr:
+ errorLoc(loc, "#line integer [\"filespec\"]\\n expected");
+ }
+
+
+
+ /***************************************************
+ * Parse doc comment embedded between t.ptr and p.
+ * Remove trailing blanks and tabs from lines.
+ * Replace all newlines with \n.
+ * Remove leading comment character from each line.
+ * Decide if it's a lineComment or a blockComment.
+ * Append to previous one for this token.
+ */
+
+ void getDocComment(Token *t, uint lineComment)
+ {
+ auto OutBuffer buf = new OutBuffer;
+ ubyte ct = t.ptr[2];
+ ubyte *q = t.ptr + 3; // start of comment text
+ int linestart = 0;
+
+ ubyte *qend = p;
+
+ if (ct == '*' || ct == '+')
+ qend -= 2;
+
+ // Scan over initial row of ****'s or ++++'s or ////'s
+ for (; q < qend; q++)
+ {
+ if (*q != ct)
+ break;
+ }
+
+ // Remove trailing row of ****'s or ++++'s
+ if (ct != '/')
+ {
+ for (; q < qend; qend--)
+ {
+ if (qend[-1] != ct)
+ break;
+ }
+ }
+
+ for (; q < qend; q++)
+ {
+ ubyte c = *q;
+
+ switch (c)
+ {
+ case '*':
+ case '+':
+ if (linestart && c == ct)
+ {
+ linestart = 0;
+ // Trim preceding whitespace up to preceding \n
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+ buf.offset--;
+ continue;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ break;
+
+ case '\r':
+ if (q[1] == '\n')
+ continue; // skip the \r
+ goto Lnewline;
+
+ default:
+ if (c == 226)
+ {
+ // If LS or PS
+ if (q[1] == 128 &&
+ (q[2] == 168 || q[2] == 169))
+ {
+ q += 2;
+ goto Lnewline;
+ }
+ }
+ linestart = 0;
+ break;
+
+ Lnewline:
+ c = '\n'; // replace all newlines with \n
+
+ case '\n':
+ linestart = 1;
+
+ // Trim trailing whitespace
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+ buf.offset--;
+
+ break;
+ }
+ buf.write(c);
+ }
+
+ // Always end with a newline
+ if (!buf.offset || buf.data[buf.offset - 1] != '\n')
+ buf.writenl();
+
+ //buf.write(cast(char)0);
+
+ // It's a line comment if the start of the doc comment comes
+ // after other non-whitespace on the same line.
+// ubyte** dc = (lineComment && anyToken)
+// ? &t.lineComment
+// : &t.blockComment;
+
+ char[] dc = (lineComment && anyToken) ? t.lineComment : t.blockComment;
+
+ // Combine with previous doc comment, if any
+ if (dc.length)
+ dc = combineComments(dc, buf.toString().dup);
+ else
+ dc = buf.toString().dup;
+
+// writefln( dc );
+
+ if (lineComment && anyToken)
+ t.lineComment = dc;
+ else
+ t.blockComment = dc;
+ }
+}
+
+// character maps
+static ubyte[256] cmtable;
+
+const int CMoctal = 0x1;
+const int CMhex = 0x2;
+const int CMidchar = 0x4;
+
+ubyte isoctal(ubyte c)
+{
+ return cmtable[c] & CMoctal;
+}
+ubyte ishex(ubyte c)
+{
+ return cmtable[c] & CMhex;
+}
+ubyte isidchar(ubyte c)
+{
+ return cmtable[c] & CMidchar;
+}
+
+static void cmtable_init()
+{
+ for (uint c = 0; c < cmtable.length; c++)
+ {
+ if ('0' <= c && c <= '7')
+ cmtable[c] |= CMoctal;
+ if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
+ cmtable[c] |= CMhex;
+ if (isalnum(c) || c == '_')
+ cmtable[c] |= CMidchar;
+ }
+}
+
+
+/+
+ struct StringValue
+ {
+ union
+ {
+ int intvalue;
+ void *ptrvalue;
+ dchar *string;
+ }
+
+ char[] lstring;
+ }
+ #define CASE_BASIC_TYPES
+ case TOKwchar: case TOKdchar:
+ case TOKbit: case TOKbool: case TOKchar:
+ case TOKint8: case TOKuns8:
+ case TOKint16: case TOKuns16:
+ case TOKint32: case TOKuns32:
+ case TOKint64: case TOKuns64:
+ case TOKfloat32: case TOKfloat64: case TOKfloat80:
+ case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:
+ case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:
+ case TOKvoid:
+
+ #define CASE_BASIC_TYPES_X(t) \
+ case TOKvoid: t = Type::tvoid; goto LabelX; \
+ case TOKint8: t = Type::tint8; goto LabelX; \
+ case TOKuns8: t = Type::tuns8; goto LabelX; \
+ case TOKint16: t = Type::tint16; goto LabelX; \
+ case TOKuns16: t = Type::tuns16; goto LabelX; \
+ case TOKint32: t = Type::tint32; goto LabelX; \
+ case TOKuns32: t = Type::tuns32; goto LabelX; \
+ case TOKint64: t = Type::tint64; goto LabelX; \
+ case TOKuns64: t = Type::tuns64; goto LabelX; \
+ case TOKfloat32: t = Type::tfloat32; goto LabelX; \
+ case TOKfloat64: t = Type::tfloat64; goto LabelX; \
+ case TOKfloat80: t = Type::tfloat80; goto LabelX; \
+ case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
+ case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
+ case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
+ case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
+ case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
+ case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
+ case TOKbit: t = Type::tbit; goto LabelX; \
+ case TOKchar: t = Type::tchar; goto LabelX; \
+ case TOKwchar: t = Type::twchar; goto LabelX; \
+ case TOKdchar: t = Type::tdchar; goto LabelX; \
+ LabelX
+ +/
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40007-Lexer.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40007-Lexer.d new file mode 100644 index 00000000..50f40a49 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40007-Lexer.d @@ -0,0 +1,2414 @@ +/+
+ * Copyright (c) 1999-2006 by Digital Mars
+ * All Rights Reserved
+ * written by Walter Bright www.digitalmars.com
+ * License for redistribution is by either the Artistic License in artistic.txt, or the GNU General Public License in gnu.txt.
+ * See the included readme.txt for details.
+ * D Language conversion by: J Duncan
+ +/
+
+/**
+ * d language lexer
+ */
+
+module dparser.Lexer;
+
+import dparser.Root;
+
+import dparser.Tokens;
+import dparser.Token;
+import dparser.Keyword;
+
+import dparser.Types;
+
+import dparser.Module;
+import dparser.Identifier;
+import dparser.unialpha;
+
+import dparser.OutBuffer;
+
+//private import std.ctype;
+//private import std.string;
+//import dwf.core.debugapi;
+
+int errno = 0;
+
+//#if _WIN32 && __DMC__
+// from \dm\src\include\setlocal.h
+//extern "C" char * __cdecl __locale_decpoint;
+char* __locale_decpoint;
+//#endif
+//const uint LS = 0x2028; // UTF line separator
+//const uint PS = 0x2029; // UTF paragraph separator
+
+//extern int isUniAlpha(unsigned u);
+//extern int HtmlNamedEntity(unsigned char *p, int length);
+
+/**
+ * Lexer object
+ */
+
+class Lexer
+{
+ static Identifier[char[]] stringtable;
+ static OutBuffer stringbuffer;
+ static Token * freelist;
+
+ Token token; // current token
+ Module mod; // current module
+ Loc loc; // for error messages
+ ubyte *base; // pointer to start of buffer
+ ubyte *end; // past end of buffer
+ ubyte *p; // current character
+ int doDocComment; // collect doc comment information
+ int anyToken; // !=0 means seen at least one token
+ int commentToken; // !=0 means comments are TOKcomment's
+
+
+ this(Module mod, ubyte* base, uint begoffset, uint endoffset, int doDocComment, int commentToken)
+ {
+ if (stringbuffer is null) {
+ stringbuffer = new OutBuffer;
+ }
+ loc = Loc(mod, 1);
+
+ this.base = base;
+ this.end = base + endoffset;
+ this.p = base + begoffset;
+ this.mod = mod;
+ this.doDocComment = doDocComment;
+ this.commentToken = commentToken;
+
+ /*
+ * If first line starts with '#!', ignore the line
+ */
+
+ if (p[0] == '#' && p[1] == '!') {
+ p += 2;
+ while (true) {
+ ubyte c = *p;
+ switch (c) {
+ case '\n':
+ p++;
+ break;
+
+ case '\r':
+ p++;
+ if (*p == '\n') {
+ p++;
+ }
+ break;
+
+ case 0:
+ case 0x1A:
+ break;
+
+ default:
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ break;
+ }
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+
+ loc.linnum = 2;
+ }
+ }
+
+
+
+ // generate a unique identifier for this string
+ static Identifier idPool(in char[] str) {
+// StringValue sv;
+// uint len = s.length;
+// StringValue sv = stringtable.update(s, len);
+// Identifier* id = cast(Identifier*) sv.ptrvalue;
+// if( id is null )
+ if ((str in stringtable) == null) {
+ stringtable[str] = new Identifier(str, TOK.TOKidentifier);
+ }
+ return(stringtable[str]);
+ }
+
+ static void initKeywords() {
+ // build character map
+ cmtable_init();
+
+ // create keyword tokens & identifiers
+ dparser.Keyword.initKeywords();
+
+ // create standard lexer tokens
+ dparser.Token.createLexerTokens();
+ }
+
+ // Combine two document comments into one.
+ static char[] combineComments(char[] c1, char[] c2) {
+ char[] c = c2;
+ if (c1.length) {
+ c = c1;
+ if (c2.length) {
+ c = c1 ~ "\n" ~ c2;
+ }
+ }
+ return(c);
+ }
+
+ // Decode UTF character. Issue error messages for invalid sequences. Return decoded character, advance p to last character in UTF sequence.
+ //! fix
+ uint decodeUTF() {
+ ubyte * s = p;
+ ubyte c = *s;
+
+ assert(c & 0x80);
+ if (!(c & 0x80)) {
+ return(c);
+ }
+
+ return(cast(uint)'X');
+ /*
+ * dchar u;
+ * uint len;
+ *
+ *
+ *
+ * // Check length of remaining string up to 6 UTF-8 characters
+ * for( len = 1; len < 6 && s[len]; len++ )
+ * {
+ *
+ * }
+ * /+
+ * uint idx = 0;
+ * char* msg = utf_decodeChar( s, len, &idx, &u );
+ * p += idx - 1;
+ * if( msg )
+ * {
+ * error(msg);
+ * }
+ * +/
+ * return u;
+ */
+ }
+
+ void error(...) {
+ if ((mod !is null) && !global.gag) {
+ writefln(formatLoc(loc, _arguments, _argptr));
+ /*
+ * char[] p = loc.toChars();
+ * if( p.length )
+ * writef( "%s: ", p );
+ * writefx( stdout, _arguments, _argptr, 1 );
+ */
+ if (global.errors >= global.max_errors) { // moderate blizzard of cascading messages
+ throw new Exception("too many errors");
+ }
+ }
+
+ global.errors++;
+ }
+
+ void errorLoc(Loc loc, ...) {
+ if ((mod !is null) && !global.gag) {
+ writefln(formatLoc(loc, _arguments, _argptr));
+ /*
+ * char[] p = loc.toChars();
+ * if( p.length )
+ * writef("%s: ", p);
+ * writefx(stdout, _arguments, _argptr, 1);
+ */
+ if (global.errors >= 20) { // moderate blizzard of cascading messages
+ throw new Exception("too many errors");
+ }
+ }
+
+ global.errors++;
+ }
+
+
+ TOK nextToken() {
+ if (token.next) {
+ Token* t = token.next;
+ memcpy(&token, t, Token.sizeof);
+// t.next = freelist;
+// freelist = t;
+ }
+ else {
+ scan(&token);
+ }
+// token.print();
+ return(token.value);
+ }
+
+ Token* peek(inout Token ct) {
+ Token* t;
+
+ if (ct.next) {
+ t = ct.next;
+ }
+ else {
+ t = new Token;
+ scan(t);
+ t.next = null;
+ ct.next = t;
+ }
+ return(t);
+ }
+
+ // Turn next token in buffer into a token.
+
+ void scan(Token* t) {
+// debug writefln("scan token");
+ uint lastLine = loc.linnum;
+ uint linnum;
+
+ t.blockComment = null;
+ t.lineComment = null;
+ while (true) {
+ t.ptr = p;
+// debug writefln( " p = %d, *p = ", cast(uint)p, cast(char)*p );
+ switch (*p) {
+ case 0:
+ case 0x1a:
+ t.value = TOK.TOKeof; // end of file
+// debug writefln( " EOF" );
+ return;
+
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ p++;
+// debug writefln( " whitespace" );
+ continue; // skip white space
+
+ case '\r':
+// debug writefln( " cr" );
+ p++;
+ if (*p != '\n') { // if CR stands by itself
+ loc.linnum++;
+ }
+ continue; // skip white space
+
+ case '\n':
+// debug writefln( " nl" );
+ p++;
+ loc.linnum++;
+ continue; // skip white space
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ t.value = number(t);
+ return;
+
+/*
+ * #if CSTRINGS
+ * case '\'':
+ * t.value = charConstant(t, 0);
+ * return;
+ *
+ * case '"':
+ * t.value = stringConstant(t,0);
+ * return;
+ *
+ * case 'l':
+ * case 'L':
+ * if( p[1] == '\'')
+ * {
+ * p++;
+ * t.value = charConstant(t, 1);
+ * return;
+ * }
+ * else if( p[1] == '"')
+ * {
+ * p++;
+ * t.value = stringConstant(t, 1);
+ * return;
+ * }
+ * #else
+ */
+ case '\'':
+// debug writefln( " char" );
+ t.value = charConstant(t, 0);
+ return;
+
+ case 'r':
+// debug writefln( " wysiwyg" );
+ if (p[1] != '"') {
+ goto case_identifier;
+ }
+ p++;
+
+ case '`':
+ t.value = wysiwygStringConstant(t, *p);
+ return;
+
+ case 'x':
+// debug writefln( " hex string" );
+ if (p[1] != '"') {
+ goto case_identifier;
+ }
+ p++;
+ t.value = hexStringConstant(t);
+ return;
+
+
+ case '"':
+// debug writefln( " string" );
+ t.value = escapeStringConstant(t, 0);
+// debug writefln( t.ustring );
+ return;
+
+ case '\\': // escaped string literal
+// debug writefln( " escaped string literal" );
+ uint c;
+ stringbuffer.offset = 0;
+ do {
+ p++;
+ c = escapeSequence();
+ stringbuffer.write(c);
+ } while (*p == '\\');
+// t.len = stringbuffer.offset;
+// stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// memcpy( t.ustring.ptr, stringbuffer.data, stringbuffer.offset );
+ t.postfix = 0;
+ t.value = TOK.TOKstring;
+ return;
+
+ case 'l':
+ case 'L':
+// #endif
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q': /*case 'r':*/
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w': /*case 'x':*/
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+case_identifier:
+ {
+// debug writefln( " identifier" );
+ ubyte c;
+ do {
+ c = *++p;
+ } while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
+
+// sv = stringtable.update((char *)t.ptr, p - t.ptr);
+ char[] tmp;
+ tmp.length = p - t.ptr;
+ memcpy(tmp.ptr, t.ptr, p - t.ptr);
+ Identifier id;
+ Identifier * pid = tmp in stringtable;
+ if (pid) {
+ id = *pid;
+ }
+
+ if (id is null) {
+ id = new Identifier(tmp, TOK.TOKidentifier);
+ stringtable[tmp] = id;
+ }
+
+ t.identifier = id;
+ t.value = cast(TOK)id.value;
+ anyToken = 1;
+
+ // if special identifier token
+ if (*t.ptr == '_') {
+ static char date[11 + 1];
+ static char time[8 + 1];
+ static char timestamp[24 + 1];
+
+ if (!date[0]) { // lazy evaluation
+ //!!
+ /+
+ * time_t t;
+ * char *p;
+ * .time(&t);
+ * p = ctime(&t);
+ * assert(p);
+ * sprintf(date.ptr, "%.6s %.4s", p + 4, p + 20);
+ * sprintf(time.ptr, "%.8s", p + 11);
+ * sprintf(timestamp.ptr, "%.24s", p);
+ +/
+ }
+
+ if (mod && id is Id.FILE) {
+ t.value = TOK.TOKstring;
+ if (loc.filename.length) {
+ t.ustring = loc.filename;
+ }
+ else {
+ t.ustring = mod.identifier.toChars();
+ }
+ goto Llen;
+ }
+ else if (mod && id == Id.LINE) {
+ t.value = TOK.TOKint64v;
+ t.uns64value = loc.linnum;
+ }
+ else if (id == Id.DATE) {
+ t.value = TOK.TOKstring;
+ //! t.ustring = date;
+ goto Llen;
+ }
+ else if (id == Id.TIME) {
+ t.value = TOK.TOKstring;
+ //! t.ustring = time;
+ goto Llen;
+ }
+ else if (id == Id.TIMESTAMP) {
+ t.value = TOK.TOKstring;
+ //! t.ustring = timestamp;
+Llen:
+ t.postfix = 0;
+// t.len = strlen((char *)t.ustring);
+ }
+ }
+ //printf("t.value = %d\n",t.value);
+ return;
+ }
+
+ // comments
+ case '/':
+ p++;
+ switch (*p) {
+ case '=':
+ p++;
+ t.value = TOK.TOKdivass;
+ return;
+
+ case '*': // '/*'
+ p++;
+ linnum = loc.linnum;
+ while (true) {
+ while (true) {
+ ubyte c = *p;
+ switch (c) {
+ case '/':
+ break;
+
+ case '\n':
+ loc.linnum++;
+ p++;
+ continue;
+
+ case '\r':
+ p++;
+ if (*p != '\n') {
+ loc.linnum++;
+ }
+ continue;
+
+ case 0:
+ case 0x1A:
+ error("unterminated /* */ comment");
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ loc.linnum++;
+ }
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+ p++;
+ if (p[-2] == '*' && p - 3 != t.ptr) {
+ break;
+ }
+ }
+
+ if (commentToken) {
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ // if /** but not /**/
+ else if (doDocComment && t.ptr[2] == '*' && p - 4 != t.ptr) {
+ getDocComment(t, lastLine == linnum); //! ?
+ }
+ continue;
+
+ case '/': // do // style comments
+ linnum = loc.linnum;
+ while (1) {
+ ubyte c = *++p;
+ switch (c) {
+ case '\n':
+ break;
+
+ case '\r':
+ if (p[1] == '\n') {
+ p++;
+ }
+ break;
+
+ case 0:
+ case 0x1a:
+ if (commentToken) {
+ p = end;
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '/') {
+ getDocComment(t, lastLine == linnum);
+ }
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ break;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+
+ if (commentToken) {
+ p++;
+ loc.linnum++;
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '/') {
+ getDocComment(t, lastLine == linnum);
+ }
+
+ p++;
+ loc.linnum++;
+ continue;
+
+ case '+':
+ {
+ int nest;
+ linnum = loc.linnum;
+ p++;
+ nest = 1;
+ while (1) {
+ ubyte c = *p;
+ switch (c) {
+ case '/':
+ p++;
+ if (*p == '+') {
+ p++;
+ nest++;
+ }
+ continue;
+
+ case '+':
+ p++;
+ if (*p == '/') {
+ p++;
+ if (--nest == 0) {
+ break;
+ }
+ }
+ continue;
+
+ case '\r':
+ p++;
+ if (*p != '\n') {
+ loc.linnum++;
+ }
+ continue;
+
+ case '\n':
+ loc.linnum++;
+ p++;
+ continue;
+
+ case 0:
+ case 0x1A:
+ error("unterminated /+ +/ comment");
+ p = end;
+ t.value = TOK.TOKeof;
+ return;
+
+ default:
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ loc.linnum++;
+ }
+ }
+ p++;
+ continue;
+ }
+ break;
+ }
+ if (commentToken) {
+ t.value = TOK.TOKcomment;
+ return;
+ }
+ if (doDocComment && t.ptr[2] == '+' && p - 4 != t.ptr) {
+ // if /++ but not /++/
+ getDocComment(t, lastLine == linnum);
+ }
+ continue;
+ }
+
+ default:
+ break;
+ }
+ t.value = TOK.TOKdiv;
+ return;
+
+ case '.':
+ p++;
+ if (isdigit(*p)) {
+ p--;
+ t.value = inreal(t);
+ }
+ else if (p[0] == '.') {
+ if (p[1] == '.') {
+ p += 2;
+ t.value = TOK.TOKdotdotdot;
+ }
+ else {
+ p++;
+ t.value = TOK.TOKslice;
+ }
+ }
+ else {
+ t.value = TOK.TOKdot;
+ }
+ return;
+
+ case '&':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKandass;
+ }
+ else if (*p == '&') {
+ p++;
+ t.value = TOK.TOKandand;
+ }
+ else {
+ t.value = TOK.TOKand;
+ }
+ return;
+
+ // |, ||, |=
+ case '|':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKorass;
+ }
+ else if (*p == '|') {
+ p++;
+ t.value = TOK.TOKoror;
+ }
+ else {
+ t.value = TOK.TOKor;
+ }
+ return;
+
+ case '-':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKminass;
+ }
+ else if (*p == '-') {
+ p++;
+ t.value = TOK.TOKminusminus;
+ }
+ else {
+ t.value = TOK.TOKmin;
+ }
+ return;
+
+ // +, +=, ++
+ case '+':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKaddass; // +=
+ }
+ else if (*p == '+') {
+ p++;
+ t.value = TOK.TOKplusplus; // ++
+ }
+ else {
+ t.value = TOK.TOKadd; // +
+ }
+ return;
+
+ // <, <=, <<=, <<, <>=, <>
+ case '<':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKle; // <=
+ }
+ else if (*p == '<') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKshlass; // <<=
+ }
+ else {
+ t.value = TOK.TOKshl; // <<
+ }
+ }
+ else if (*p == '>') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKleg; // <>=
+ }
+ else {
+ t.value = TOK.TOKlg; // <>
+ }
+ }
+ else {
+ t.value = TOK.TOKlt; // <
+ }
+ return;
+
+ // >, >>, >>>, >=, >>=, >>>=
+ case '>':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKge; // >=
+ }
+ else if (*p == '>') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKshrass; // >>=
+ }
+ else if (*p == '>') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKushrass; // >>>=
+ }
+ else {
+ t.value = TOK.TOKushr; // >>>
+ }
+ }
+ else {
+ t.value = TOK.TOKshr; // >>
+ }
+ }
+ else {
+ t.value = TOK.TOKgt; // >
+ }
+ return;
+
+ case '!':
+ p++;
+ if (*p == '=') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKnotidentity; // !==
+ }
+ else {
+ t.value = TOK.TOKnotequal; // !=
+ }
+ }
+ else if (*p == '<') {
+ p++;
+ if (*p == '>') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKunord; // !<>=
+ }
+ else {
+ t.value = TOK.TOKue; // !<>
+ }
+ }
+ else if (*p == '=') {
+ p++;
+ t.value = TOK.TOKug; // !<=
+ }
+ else {
+ t.value = TOK.TOKuge; // !<
+ }
+ }
+ else if (*p == '>') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKul; // !>=
+ }
+ else {
+ t.value = TOK.TOKule; // !>
+ }
+ }
+ else {
+ t.value = TOK.TOKnot; // !
+ }
+ return;
+
+ case '=':
+ p++;
+ if (*p == '=') {
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKidentity; // ===
+ }
+ else {
+ t.value = TOK.TOKequal; // ==
+ }
+ }
+ else {
+ t.value = TOK.TOKassign; // =
+ }
+ return;
+
+ case '~':
+ p++;
+ if (*p == '=') {
+ p++;
+ t.value = TOK.TOKcatass; // ~=
+ }
+ else {
+ t.value = TOK.TOKtilde; // ~
+ }
+ return;
+
+ // SINGLE
+ case '(': p++; t.value = TOK.TOKlparen; return;
+
+ case ')': p++; t.value = TOK.TOKrparen; return;
+
+ case '[': p++; t.value = TOK.TOKlbracket; return;
+
+ case ']': p++; t.value = TOK.TOKrbracket; return;
+
+ case '{': p++; t.value = TOK.TOKlcurly; return;
+
+ case '}': p++; t.value = TOK.TOKrcurly; return;
+
+ case '?': p++; t.value = TOK.TOKquestion; return;
+
+ case ',': p++; t.value = TOK.TOKcomma; return;
+
+ case ';': p++; t.value = TOK.TOKsemicolon; return;
+
+ case ':': p++; t.value = TOK.TOKcolon; return;
+
+ case '$': p++; t.value = TOK.TOKdollar; return;
+
+ // DOUBLE
+ case '*': p++; if (*p == '=') {
+ p++; t.value = TOK.TOKmulass;
+ }
+ else {
+ t.value = TOK.TOKmul;
+ } return;
+
+ case '%': p++; if (*p == '=') {
+ p++; t.value = TOK.TOKmodass;
+ }
+ else {
+ t.value = TOK.TOKmod;
+ } return;
+
+ case '^': p++; if (*p == '=') {
+ p++; t.value = TOK.TOKxorass;
+ }
+ else {
+ t.value = TOK.TOKxor;
+ } return;
+
+// removed 148 case '~': p++; if( *p == '=' ) { p++; t.value = TOK.TOKcatass; } else t.value = TOK.TOKtilde; return;
+
+
+ case '#':
+ p++;
+ Pragma();
+ continue;
+
+ default:
+ {
+ debug writefln(" default char");
+ ubyte c = *p;
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ // Check for start of unicode identifier
+ if (isUniAlpha(u)) {
+ goto case_identifier;
+ }
+
+ if (u == PS || u == LS) {
+ loc.linnum++;
+ p++;
+ continue;
+ }
+ }
+ if (isprint(c)) {
+ error("unsupported char '%s'", cast(char)c);
+ }
+ else {
+ error("unsupported char 0x%02x", cast(ubyte)c);
+ }
+ p++;
+ continue;
+ }
+ }
+ }
+ }
+
+
+
+ // Parse escape sequence.
+ uint escapeSequence() {
+ uint c;
+ int n;
+ int ndigits;
+
+ c = *p;
+ switch (c) {
+ case '\'':
+ case '"':
+ case '?':
+ case '\\':
+Lconsume:
+ p++;
+ break;
+
+ case 'a': c = 7; goto Lconsume;
+
+ case 'b': c = 8; goto Lconsume;
+
+ case 'f': c = 12; goto Lconsume;
+
+ case 'n': c = 10; goto Lconsume;
+
+ case 'r': c = 13; goto Lconsume;
+
+ case 't': c = 9; goto Lconsume;
+
+ case 'v': c = 11; goto Lconsume;
+
+ case 'u':
+ ndigits = 4;
+ goto Lhex;
+
+ case 'U':
+ ndigits = 8;
+ goto Lhex;
+
+ case 'x':
+ ndigits = 2;
+Lhex:
+ p++;
+ c = *p;
+ if (ishex(c)) {
+ uint v;
+ n = 0;
+ v = 0;
+ while (1) {
+ if (isdigit(c)) {
+ c -= '0';
+ }
+ else if (islower(c)) {
+ c -= 'a' - 10;
+ }
+ else {
+ c -= 'A' - 10;
+ }
+ v = v * 16 + c;
+ c = *++p;
+ if (++n == ndigits) {
+ break;
+ }
+ if (!ishex(c)) {
+ error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
+ break;
+ }
+ }
+//! if( ndigits != 2 && !utf_isValidDchar(v))
+//! error("invalid UTF character \\U%08x", v);
+ c = v;
+ }
+ else {
+ error("undefined escape hex sequence \\%s\n", c);
+ }
+ break;
+
+ case '&': // named character entity
+ for (ubyte *idstart = ++p; 1; p++) {
+ switch (*p) {
+ case ';':
+ //!!!
+ /+
+ * c = HtmlNamedEntity(idstart, p - idstart);
+ * if( c == ~0 )
+ * {
+ * error("unnamed character entity &%.*s;", p - idstart, idstart);
+ * c = ' ';
+ * }
+ *
+ * p++;
+ +/
+ break;
+
+ default:
+ if (isalpha(*p) || (p != idstart + 1 && isdigit(*p))) {
+ continue;
+ }
+ error("unterminated named entity");
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0:
+ case 0x1a: // end of file
+ c = '\\';
+ break;
+
+ default:
+ if (isoctal(c)) {
+ ubyte v;
+ n = 0;
+ do {
+ v = v * 8 + (c - '0');
+ c = *++p;
+ } while (++n < 3 && isoctal(c));
+ c = v;
+ }
+ else {
+ error("undefined escape sequence \\%s\n", c);
+ }
+ break;
+ }
+ return(c);
+ }
+
+ /**************************************
+ */
+
+ TOK wysiwygStringConstant(Token *t, int tc) {
+ uint c;
+ Loc start = loc;
+
+ p++;
+ stringbuffer.offset = 0;
+ while (1) {
+ c = *p++;
+ switch (c) {
+ case '\n':
+ loc.linnum++;
+ break;
+
+ case '\r':
+ if (*p == '\n') {
+ continue; // ignore
+ }
+ c = '\n'; // treat EndOfLine as \n character
+ loc.linnum++;
+ break;
+
+ case 0:
+ case 0x1a:
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+ t.postfix = 0;
+ return(TOK.TOKstring);
+
+ case '"':
+ case '`':
+ if (c == tc) {
+// t.len = stringbuffer.offset;
+ stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+// memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+ return(TOK.TOKstring);
+ }
+ break;
+
+ default:
+ if (c & 0x80) {
+ p--;
+ uint u = decodeUTF();
+ p++;
+ if (u == PS || u == LS) {
+ loc.linnum++;
+ }
+ stringbuffer.write(u);
+ continue;
+ }
+ break;
+ }
+ stringbuffer.write(c);
+ }
+ }
+
+ /**************************************
+ * Lex hex strings:
+ * x"0A ae 34FE BD"
+ */
+
+ TOK hexStringConstant(Token *t) {
+ uint c;
+ Loc start = loc;
+ uint n = 0;
+ uint v;
+
+ p++;
+ stringbuffer.offset = 0;
+ while (1) {
+ c = *p++;
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ continue; // skip white space
+
+ case '\r':
+ if (*p == '\n') {
+ continue; // ignore
+ }
+
+ // Treat isolated '\r' as if it were a '\n'
+ case '\n':
+ loc.linnum++;
+ continue;
+
+ case 0:
+ case 0x1a:
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+ t.postfix = 0;
+ return(TOK.TOKstring);
+
+ case '"':
+ if (n & 1) {
+ error("odd number (%d) of hex characters in hex string", n);
+ stringbuffer.write(v);
+ }
+// t.len = stringbuffer.offset;
+// stringbuffer.write(cast(byte)0);
+ t.ustring = stringbuffer.toString;
+// t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+// memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+ return(TOK.TOKstring);
+
+ default:
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ }
+ else if (c >= 'a' && c <= 'f') {
+ c -= 'a' - 10;
+ }
+ else if (c >= 'A' && c <= 'F') {
+ c -= 'A' - 10;
+ }
+ else if (c & 0x80) {
+ p--;
+ uint u = decodeUTF();
+ p++;
+ if (u == PS || u == LS) {
+ loc.linnum++;
+ }
+ else {
+ error("non-hex character \\u%x", u);
+ }
+ }
+ else {
+ error("non-hex character '%s'", c);
+ }
+ if (n & 1) {
+ v = (v << 4) | c;
+ stringbuffer.write(v);
+ }
+ else {
+ v = c;
+ }
+ n++;
+ break;
+ }
+ }
+ }
+
+ /**************************************
+ */
+
+ TOK escapeStringConstant(Token *t, int wide) {
+ uint c;
+ Loc start = loc;
+
+ p++;
+ stringbuffer.offset = 0;
+ // debug writefln( "escape string constant: %s", std.string.toString( cast(char*)p ) );
+ while (1) {
+ c = *p++;
+ switch (c) {
+ case '\\':
+ switch (*p) {
+ case 'u':
+ case 'U':
+ case '&':
+ c = escapeSequence();
+ stringbuffer.write(c);
+ continue;
+
+ default:
+ c = escapeSequence();
+ break;
+ }
+ break;
+
+ case '\n':
+ loc.linnum++;
+ break;
+
+ case '\r':
+ if (*p == '\n') {
+ continue; // ignore
+ }
+ c = '\n'; // treat EndOfLine as \n character
+ loc.linnum++;
+ break;
+
+ case '"':
+// writefln( "end of string: ", stringbuffer.toString );
+ t.ustring = stringbuffer.toString().dup;
+ // t.len = stringbuffer.offset;
+ // stringbuffer.write(cast(byte)0);
+ // t.ustring = (ubyte *)mem.malloc(stringbuffer.offset);
+ // memcpy(t.ustring, stringbuffer.data, stringbuffer.offset);
+ stringPostfix(t);
+
+ return(TOK.TOKstring);
+
+ case 0:
+ case 0x1a:
+ p--;
+ error("unterminated string constant starting at %s", start.toChars());
+ t.ustring = "";
+// t.len = 0;
+ t.postfix = 0;
+ return(TOK.TOKstring);
+
+ default:
+ if (c & 0x80) {
+ p--;
+ c = decodeUTF();
+ if (c == LS || c == PS) {
+ c = '\n';
+ loc.linnum++;
+ }
+ p++;
+ stringbuffer.write(cast(char)c);
+ continue;
+ }
+ break;
+ }
+ stringbuffer.write(cast(char)c);
+// writefln( stringbuffer.toString );
+ }
+ }
+
+ //**************************************
+ TOK charConstant(Token *t, int wide) {
+ uint c;
+ TOK tk = TOK.TOKcharv;
+
+ //printf("Lexer.charConstant\n");
+ p++;
+ c = *p++;
+ switch (c) {
+ case '\\':
+ switch (*p) {
+ case 'u':
+ t.uns64value = escapeSequence();
+ tk = TOK.TOKwcharv;
+ break;
+
+ case 'U':
+ case '&':
+ t.uns64value = escapeSequence();
+ tk = TOK.TOKdcharv;
+ break;
+
+ default:
+ t.uns64value = escapeSequence();
+ break;
+ }
+ break;
+
+ case '\n':
+L1:
+ loc.linnum++;
+
+ case '\r':
+ case 0:
+ case 0x1a:
+ case '\'':
+ error("unterminated character constant");
+ return(tk);
+
+ default:
+ if (c & 0x80) {
+ p--;
+ c = decodeUTF();
+ p++;
+ if (c == LS || c == PS) {
+ goto L1;
+ }
+ if (c < 0xd800 || (c >= 0xe000 && c < 0xfffe)) {
+ tk = TOK.TOKwcharv;
+ }
+ else {
+ tk = TOK.TOKdcharv;
+ }
+ }
+ t.uns64value = c;
+ break;
+ }
+
+ if (*p != '\'') {
+ error("unterminated character constant");
+ return(tk);
+ }
+ p++;
+ return(tk);
+ }
+
+ // Get postfix of string literal.
+ void stringPostfix(Token *t) {
+ switch (*p) {
+ case 'c':
+ case 'w':
+ case 'd':
+ t.postfix = *p;
+ p++;
+ break;
+
+ default:
+ t.postfix = 0;
+ break;
+ }
+ }
+
+ /***************************************
+ * Read \u or \U unicode sequence
+ * Input:
+ * u 'u' or 'U'
+ */
+ /*
+ * uint Wchar(uint u)
+ * {
+ * uint value;
+ * uint n;
+ * ubyte c;
+ * uint nchars;
+ *
+ * nchars = (u == 'U') ? 8 : 4;
+ * value = 0;
+ * for (n = 0; 1; n++)
+ * {
+ * ++p;
+ * if( n == nchars)
+ * break;
+ * c = *p;
+ * if( !ishex(c))
+ * {
+ * error("\\%s sequence must be followed by %d hex characters", u, nchars);
+ * break;
+ * }
+ * if( isdigit(c))
+ * c -= '0';
+ * else if( islower(c))
+ * c -= 'a' - 10;
+ * else
+ * c -= 'A' - 10;
+ * value <<= 4;
+ * value |= c;
+ * }
+ * return value;
+ * }
+ */
+
+ /**************************************
+ * Read in a number.
+ * If it's an integer, store it in tok.TKutok.Vlong.
+ * integers can be decimal, octal or hex
+ * Handle the suffixes U, UL, LU, L, etc.
+ * If it's double, store it in tok.TKutok.Vdouble.
+ * Returns:
+ * TKnum
+ * TKdouble,...
+ */
+
+ TOK number(Token *t) {
+ //debug writefln("Lexer.number()");
+ // We use a state machine to collect numbers
+ enum STATE {
+ STATE_initial,
+ STATE_0,
+ STATE_decimal,
+ STATE_octal,
+ STATE_octale,
+ STATE_hex,
+ STATE_binary,
+ STATE_hex0,
+ STATE_binary0,
+ STATE_hexh,
+ STATE_error
+ }
+
+ enum FLAGS {
+ FLAGS_decimal = 1, // decimal
+ FLAGS_unsigned = 2, // u or U suffix
+ FLAGS_long = 4, // l or L suffix
+ }
+ FLAGS flags = FLAGS.FLAGS_decimal;
+
+ int i;
+ TOK result;
+ int base;
+
+ stringbuffer.offset = 0;
+// stringbuffer.data = null;
+ STATE state = STATE.STATE_initial;
+ ubyte * start = p;
+
+ TOK _isreal() {
+ p = start;
+ return(inreal(t));
+ }
+
+ while (true) {
+ char c = cast(char)*p;
+ switch (state) {
+ case STATE.STATE_initial: // opening state
+ if (c == '0') {
+ state = STATE.STATE_0;
+ }
+ else {
+ state = STATE.STATE_decimal;
+ }
+ break;
+
+ case STATE.STATE_0:
+ flags = cast(FLAGS)(flags & ~FLAGS.FLAGS_decimal);
+ switch (c) {
+ // #if ZEROH
+// case 'H': // 0h
+// case 'h':
+// goto hexh;
+ // #endif
+ case 'X':
+ case 'x':
+ state = STATE.STATE_hex0;
+ break;
+
+ case '.':
+ if (p[1] == '.') { // .. is a separate token
+ goto done;
+ }
+
+ case 'i':
+ case 'f':
+ case 'F':
+ goto _Real;
+
+ // #if ZEROH
+// case 'E':
+// case 'e':
+// goto case_hex;
+ // #endif
+ case 'B':
+ case 'b':
+ state = STATE.STATE_binary0;
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ state = STATE.STATE_octal;
+ break;
+
+ // #if ZEROH
+// case '8': case '9': case 'A':
+// case 'C': case 'D': case 'F':
+// case 'a': case 'c': case 'd': case 'f':
+// case_hex:
+// state = STATE.STATE_hexh;
+// break;
+ // #endif
+ case '_':
+ state = STATE.STATE_octal;
+ p++;
+ continue;
+
+ default:
+ goto done;
+ }
+ break;
+
+ case STATE.STATE_decimal: // reading decimal number
+
+ // if its not a digit - decimal complete or not a decimal
+ if (!isdigit(c)) {
+// debug writefln( "\tnon-digit( %s )", c );
+ // #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+ // #endif
+ //! wtf ?
+ // ignore embedded _
+ if (c == '_') {
+ p++;
+ continue;
+ }
+
+ // check decimal point - make real
+ if (c == '.' && p[1] != '.') {
+ goto _Real;
+ }
+
+ // check for mantra - make real
+ if (c == 'i' || c == 'f' || c == 'F' || c == 'e' || c == 'E') {
+_Real: // It's a real number. Back up and rescan as a real
+ p = start;
+ return(inreal(t));
+ }
+
+ goto done;
+ }
+ break;
+
+ case STATE.STATE_hex0: // reading hex number
+ case STATE.STATE_hex:
+ if (!ishex(c)) {
+ if (c == '_') { // ignore embedded _
+ p++;
+ continue;
+ }
+ if (c == '.' && p[1] != '.') {
+ goto _Real;
+ }
+ if (c == 'P' || c == 'p' || c == 'i') {
+ goto _Real;
+ }
+ if (state == STATE.STATE_hex0) {
+ error("Hex digit expected, not '%s'", c);
+ }
+ goto done;
+ }
+ state = STATE.STATE_hex;
+ break;
+
+ // #if ZEROH
+// hexh:
+// state = STATE.STATE_hexh;
+//
+// case STATE.STATE_hexh: // parse numbers like 0FFh
+// if( !ishex(c))
+// {
+// if( c == 'H' || c == 'h')
+// {
+// p++;
+// base = 16;
+// goto done;
+// }
+// else
+// {
+// // Check for something like 1E3 or 0E24
+// if( memchr(stringbuffer.data.ptr, 'E', stringbuffer.offset) || memchr( stringbuffer.data.ptr, 'e', stringbuffer.offset))
+// goto _Real;
+// error("Hex digit expected, not '%s'", c);
+// goto done;
+// }
+// }
+// break;
+ // #endif
+
+ case STATE.STATE_octal: // reading octal number
+ case STATE.STATE_octale: // reading octal number with non-octal digits
+ if (!isoctal(c)) {
+// #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+// #endif
+ if (c == '_') { // ignore embedded _
+ p++;
+ continue;
+ }
+ if (c == '.' && p[1] != '.') {
+ goto _Real;
+ }
+ if (c == 'i') {
+ goto _Real;
+ }
+ if (isdigit(c)) {
+ state = STATE.STATE_octale;
+ }
+ else {
+ goto done;
+ }
+ }
+ break;
+
+ case STATE.STATE_binary0: // starting binary number
+ case STATE.STATE_binary: // reading binary number
+ if (c != '0' && c != '1') {
+ // #if ZEROH
+// if( ishex(c) || c == 'H' || c == 'h' )
+// goto hexh;
+ // #endif
+ if (c == '_') { // ignore embedded _
+ p++;
+ continue;
+ }
+ if (state == STATE.STATE_binary0) {
+ error("binary digit expected");
+ state = STATE.STATE_error;
+ break;
+ }
+ else {
+ goto done;
+ }
+ }
+ state = STATE.STATE_binary;
+ break;
+
+ case STATE.STATE_error: // for error recovery
+ if (!isdigit(c)) { // scan until non-digit
+ goto done;
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+ stringbuffer.write(cast(char)c);
+ p++;
+ }
+done:
+ stringbuffer.write(cast(char)0); // terminate string
+
+// debug writefln( "\tdigit complete( %s )", stringbuffer.toString );
+
+ if (state == STATE.STATE_octale) {
+ error("Octal digit expected");
+ }
+
+ uinteger_t n; // unsigned >=64 bit integer type
+
+ if (stringbuffer.offset == 2 && (state == STATE.STATE_decimal || state == STATE.STATE_0)) {
+ n = stringbuffer.data[0] - '0';
+ }
+ else {
+ // Convert string to integer
+ char* p = cast(char*)stringbuffer.data.ptr;
+ int r = 10;
+ int d;
+ if (*p == '0') {
+ if (p[1] == 'x' || p[1] == 'X') {
+ // "0x#"
+ p += 2;
+ r = 16;
+ }
+ else if (p[1] == 'b' || p[1] == 'B') {
+ // "0b#" - binary
+ p += 2;
+ r = 2;
+ }
+ else if (isdigit(p[1])) {
+ p += 1;
+ r = 8;
+ }
+ }
+
+ n = 0;
+
+ while (true) {
+ if (*p >= '0' && *p <= '9') {
+ d = *p - '0';
+ }
+ else if (*p >= 'a' && *p <= 'z') {
+ d = *p - 'a' + 10;
+ }
+ else if (*p >= 'A' && *p <= 'Z') {
+ d = *p - 'A' + 10;
+ }
+ else {
+ break;
+ }
+
+ if (d >= r) {
+ break;
+ }
+
+ if (n * r + d < n) {
+ error("integer overflow");
+ break;
+ }
+
+ n = n * r + d;
+ p++;
+ }
+
+ // if n needs more than 64 bits
+ if (n.sizeof > 8 && n > 0xffffffffffffffffL) {
+ error("integer overflow");
+ }
+ }
+
+ // Parse trailing 'u', 'U', 'l' or 'L' in any combination
+ while (true) {
+ ubyte f;
+ switch (*p) {
+ case 'U':
+ case 'u':
+ f = FLAGS.FLAGS_unsigned;
+ goto L1;
+
+ case 'L':
+ case 'l':
+ f = FLAGS.FLAGS_long;
+L1:
+ p++;
+ if (flags & f) {
+ error("unrecognized token");
+ }
+ flags = cast(FLAGS)(flags | f);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ switch (flags) {
+ case 0:
+ /* Octal or Hexadecimal constant.
+ * First that fits: int, uint, long, ulong
+ */
+ if (n & 0x8000000000000000L) {
+ result = TOK.TOKuns64v;
+ }
+ else if (n & 0xffffffff00000000L) {
+ result = TOK.TOKint64v;
+ }
+ else if (n & 0x80000000) {
+ result = TOK.TOKuns32v;
+ }
+ else {
+ result = TOK.TOKint32v;
+ }
+ break;
+
+ case FLAGS.FLAGS_decimal:
+ /* First that fits: int, long, long long
+ */
+ if (n & 0x8000000000000000L) {
+ error("signed integer overflow");
+ result = TOK.TOKuns64v;
+ }
+ else if (n & 0xffffffff80000000L) {
+ result = TOK.TOKint64v;
+ }
+ else {
+ result = TOK.TOKint32v;
+ }
+ break;
+
+ case FLAGS.FLAGS_unsigned:
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned:
+ /* First that fits: uint, ulong
+ */
+ if (n & 0xffffffff00000000L) {
+ result = TOK.TOKuns64v;
+ }
+ else {
+ result = TOK.TOKuns32v;
+ }
+ break;
+
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_long:
+ if (n & 0x8000000000000000L) {
+ error("signed integer overflow");
+ result = TOK.TOKuns64v;
+ }
+ else {
+ result = TOK.TOKint64v;
+ }
+ break;
+
+ case FLAGS.FLAGS_long:
+ if (n & 0x8000000000000000L) {
+ result = TOK.TOKuns64v;
+ }
+ else {
+ result = TOK.TOKint64v;
+ }
+ break;
+
+ case FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+ case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+ result = TOK.TOKuns64v;
+ break;
+
+ default:
+ debug writefln("%x", flags);
+ assert(0);
+ }
+ t.uns64value = n;
+ return(result);
+ }
+
+ /**************************************
+ * Read in characters, converting them to real.
+ * Bugs:
+ * Exponent overflow not detected.
+ * Too much requested precision is not detected.
+ */
+
+ TOK inreal(Token *t) {
+ int dblstate;
+ uint c;
+ char hex; // is this a hexadecimal-floating-constant?
+ TOK result;
+
+ //printf("Lexer.inreal()\n");
+ stringbuffer.offset = 0;
+ dblstate = 0;
+ hex = 0;
+Lnext:
+ while (1) {
+ // Get next char from input
+ c = *p++;
+ //printf("dblstate = %d, c = '%s'\n", dblstate, c);
+ while (1) {
+ switch (dblstate) {
+ case 0: // opening state
+ if (c == '0') {
+ dblstate = 9;
+ }
+ else if (c == '.') {
+ dblstate = 3;
+ }
+ else {
+ dblstate = 1;
+ }
+ break;
+
+ case 9:
+ dblstate = 1;
+ if (c == 'X' || c == 'x') {
+ hex++;
+ break;
+ }
+
+ case 1: // digits to left of .
+ case 3: // digits to right of .
+ case 7: // continuing exponent digits
+ if (!isdigit(c) && !(hex && isxdigit(c))) {
+ if (c == '_') {
+ goto Lnext; // ignore embedded '_'
+ }
+ dblstate++;
+ continue;
+ }
+ break;
+
+ case 2: // no more digits to left of .
+ if (c == '.') {
+ dblstate++;
+ break;
+ }
+
+ case 4: // no more digits to right of .
+ if ((c == 'E' || c == 'e') || hex && (c == 'P' || c == 'p')) {
+ dblstate = 5;
+ hex = 0; // exponent is always decimal
+ break;
+ }
+ if (hex) {
+ error("binary-exponent-part required");
+ }
+ goto done;
+
+ case 5: // looking immediately to right of E
+ dblstate++;
+ if (c == '-' || c == '+') {
+ break;
+ }
+
+ case 6: // 1st exponent digit expected
+ if (!isdigit(c)) {
+ error("exponent expected");
+ }
+ dblstate++;
+ break;
+
+ case 8: // past end of exponent digits
+ goto done;
+ }
+ break;
+ }
+ stringbuffer.write(c);
+ }
+done:
+ p--;
+
+ stringbuffer.write(cast(byte)0);
+
+// #if _WIN32 && __DMC__
+ char *save = __locale_decpoint;
+
+ __locale_decpoint = ".";
+// #endif
+ t.float80value = strtold(cast(char *)stringbuffer.data.ptr, null);
+ errno = 0;
+ switch (*p) {
+ case 'F':
+ case 'f':
+ strtof(cast(char *)stringbuffer.data.ptr, null);
+ result = TOK.TOKfloat32v;
+ p++;
+ break;
+
+ default:
+ strtod(cast(char *)stringbuffer.data.ptr, null);
+ result = TOK.TOKfloat64v;
+ break;
+
+ case 'L':
+ case 'l':
+ result = TOK.TOKfloat80v;
+ p++;
+ break;
+ }
+ if (*p == 'i' || *p == 'I') {
+ p++;
+ switch (result) {
+ case TOK.TOKfloat32v:
+ result = TOK.TOKimaginary32v;
+ break;
+
+ case TOK.TOKfloat64v:
+ result = TOK.TOKimaginary64v;
+ break;
+
+ case TOK.TOKfloat80v:
+ result = TOK.TOKimaginary80v;
+ break;
+ }
+ }
+// #if _WIN32 && __DMC__
+ __locale_decpoint = save;
+// #endif
+ if (errno == ERANGE) {
+ error("number is not representable");
+ }
+ return(result);
+ }
+
+
+
+
+ /*********************************************
+ * Do pragma.
+ * Currently, the only pragma supported is:
+ * #line linnum [filespec]
+ */
+
+ void Pragma() {
+ Token tok;
+ int linnum;
+
+ char[] filespec;
+ Loc loc = this.loc;
+
+ scan(&tok);
+
+ if (tok.value != TOK.TOKidentifier || tok.identifier != Id.line) {
+ goto Lerr;
+ }
+
+ scan(&tok);
+ if (tok.value == TOK.TOKint32v || tok.value == TOK.TOKint64v) {
+ linnum = tok.uns64value - 1;
+ }
+ else {
+ goto Lerr;
+ }
+
+ while (1) {
+ switch (*p) {
+ case 0:
+ case 0x1a:
+ case '\n':
+Lnewline:
+ this.loc.linnum = linnum;
+ if (filespec.length) {
+ this.loc.filename = filespec;
+ }
+ return;
+
+ case '\r':
+ p++;
+ if (*p != '\n') {
+ p--;
+ goto Lnewline;
+ }
+ continue;
+
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\f':
+ p++;
+ continue; // skip white space
+
+ case '_':
+ if (mod && memcmp(p, cast(char*)"__FILE__", 8) == 0) {
+ p += 8;
+//! filespec = mem.strdup(loc.filename ? loc.filename : mod.identifier.toChars());
+ }
+ continue;
+
+ case '"':
+ if (filespec) {
+ goto Lerr;
+ }
+ stringbuffer.offset = 0;
+ p++;
+ while (1) {
+ uint c;
+ c = *p;
+ switch (c) {
+ case '\n':
+ case '\r':
+ case 0:
+ case 0x1a:
+ goto Lerr;
+
+ case '"':
+ stringbuffer.write(cast(byte)0);
+ // filespec = mem.strdup((char *)stringbuffer.data);
+ filespec = stringbuffer.toString.dup;
+ p++;
+ break;
+
+ default:
+ if (c & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ goto Lerr;
+ }
+ }
+ stringbuffer.write(c);
+ p++;
+ continue;
+ }
+ break;
+ }
+ continue;
+
+ default:
+ if (*p & 0x80) {
+ uint u = decodeUTF();
+ if (u == PS || u == LS) {
+ goto Lnewline;
+ }
+ }
+ goto Lerr;
+ }
+ }
+
+Lerr:
+ errorLoc(loc, "#line integer [\"filespec\"]\\n expected");
+ }
+
+
+
+ /***************************************************
+ * Parse doc comment embedded between t.ptr and p.
+ * Remove trailing blanks and tabs from lines.
+ * Replace all newlines with \n.
+ * Remove leading comment character from each line.
+ * Decide if it's a lineComment or a blockComment.
+ * Append to previous one for this token.
+ */
+
+ void getDocComment(Token *t, uint lineComment) {
+ auto OutBuffer buf = new OutBuffer;
+ ubyte ct = t.ptr[2];
+ ubyte *q = t.ptr + 3; // start of comment text
+ int linestart = 0;
+
+ ubyte *qend = p;
+
+ if (ct == '*' || ct == '+') {
+ qend -= 2;
+ }
+
+ // Scan over initial row of ****'s or ++++'s or ////'s
+ for (; q < qend; q++) {
+ if (*q != ct) {
+ break;
+ }
+ }
+
+ // Remove trailing row of ****'s or ++++'s
+ if (ct != '/') {
+ for (; q < qend; qend--) {
+ if (qend[-1] != ct) {
+ break;
+ }
+ }
+ }
+
+ for (; q < qend; q++) {
+ ubyte c = *q;
+
+ switch (c) {
+ case '*':
+ case '+':
+ if (linestart && c == ct) {
+ linestart = 0;
+ // Trim preceding whitespace up to preceding \n
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t')) {
+ buf.offset--;
+ }
+ continue;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ break;
+
+ case '\r':
+ if (q[1] == '\n') {
+ continue; // skip the \r
+ }
+ goto Lnewline;
+
+ default:
+ if (c == 226) {
+ // If LS or PS
+ if (q[1] == 128 &&
+ (q[2] == 168 || q[2] == 169)) {
+ q += 2;
+ goto Lnewline;
+ }
+ }
+ linestart = 0;
+ break;
+
+Lnewline:
+ c = '\n'; // replace all newlines with \n
+
+ case '\n':
+ linestart = 1;
+
+ // Trim trailing whitespace
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t')) {
+ buf.offset--;
+ }
+
+ break;
+ }
+ buf.write(c);
+ }
+
+ // Always end with a newline
+ if (!buf.offset || buf.data[buf.offset - 1] != '\n') {
+ buf.writenl();
+ }
+
+ //buf.write(cast(char)0);
+
+ // It's a line comment if the start of the doc comment comes
+ // after other non-whitespace on the same line.
+// ubyte** dc = (lineComment && anyToken)
+// ? &t.lineComment
+// : &t.blockComment;
+
+ char[] dc = (lineComment && anyToken) ? t.lineComment : t.blockComment;
+
+ // Combine with previous doc comment, if any
+ if (dc.length) {
+ dc = combineComments(dc, buf.toString().dup);
+ }
+ else {
+ dc = buf.toString().dup;
+ }
+
+// writefln( dc );
+
+ if (lineComment && anyToken) {
+ t.lineComment = dc;
+ }
+ else {
+ t.blockComment = dc;
+ }
+ }
+}
+
+// character maps
+static ubyte[256] cmtable;
+
+const int CMoctal = 0x1;
+const int CMhex = 0x2;
+const int CMidchar = 0x4;
+
+ubyte isoctal(ubyte c) {
+ return(cmtable[c] & CMoctal);
+}
+ubyte ishex(ubyte c) {
+ return(cmtable[c] & CMhex);
+}
+ubyte isidchar(ubyte c) {
+ return(cmtable[c] & CMidchar);
+}
+
+static void cmtable_init() {
+ for (uint c = 0; c < cmtable.length; c++) {
+ if ('0' <= c && c <= '7') {
+ cmtable[c] |= CMoctal;
+ }
+ if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) {
+ cmtable[c] |= CMhex;
+ }
+ if (isalnum(c) || c == '_') {
+ cmtable[c] |= CMidchar;
+ }
+ }
+}
+
+
+/+
+ * struct StringValue
+ * {
+ * union
+ * {
+ * int intvalue;
+ * void *ptrvalue;
+ * dchar *string;
+ * }
+ *
+ * char[] lstring;
+ * }
+ * #define CASE_BASIC_TYPES
+ * case TOKwchar: case TOKdchar:
+ * case TOKbit: case TOKbool: case TOKchar:
+ * case TOKint8: case TOKuns8:
+ * case TOKint16: case TOKuns16:
+ * case TOKint32: case TOKuns32:
+ * case TOKint64: case TOKuns64:
+ * case TOKfloat32: case TOKfloat64: case TOKfloat80:
+ * case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:
+ * case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:
+ * case TOKvoid:
+ *
+ * #define CASE_BASIC_TYPES_X(t) \
+ * case TOKvoid: t = Type::tvoid; goto LabelX; \
+ * case TOKint8: t = Type::tint8; goto LabelX; \
+ * case TOKuns8: t = Type::tuns8; goto LabelX; \
+ * case TOKint16: t = Type::tint16; goto LabelX; \
+ * case TOKuns16: t = Type::tuns16; goto LabelX; \
+ * case TOKint32: t = Type::tint32; goto LabelX; \
+ * case TOKuns32: t = Type::tuns32; goto LabelX; \
+ * case TOKint64: t = Type::tint64; goto LabelX; \
+ * case TOKuns64: t = Type::tuns64; goto LabelX; \
+ * case TOKfloat32: t = Type::tfloat32; goto LabelX; \
+ * case TOKfloat64: t = Type::tfloat64; goto LabelX; \
+ * case TOKfloat80: t = Type::tfloat80; goto LabelX; \
+ * case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
+ * case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
+ * case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
+ * case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
+ * case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
+ * case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
+ * case TOKbit: t = Type::tbit; goto LabelX; \
+ * case TOKchar: t = Type::tchar; goto LabelX; \
+ * case TOKwchar: t = Type::twchar; goto LabelX; \
+ * case TOKdchar: t = Type::tdchar; goto LabelX; \
+ * LabelX
+ +/
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40010-template.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40010-template.d new file mode 100644 index 00000000..33a4155b --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40010-template.d @@ -0,0 +1,30 @@ + +template Foo(T, U) +{ + class Bar { } + + T foo(T t, U u) + { + } + + T abc; + + typedef T *FooType; + typedef Tte **FooType0; + typedef int *FooType1; + typedef const char FooType2; +} + +alias Foo!(int, char) f; +f.Bar b; +f.foo(1, 2); +f.abc = 3; + +to!string(10.0); +TFoo!int.t x; + +class Abc(T) +{ + T t; +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40011-template.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40011-template.d new file mode 100644 index 00000000..5c106063 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40011-template.d @@ -0,0 +1,27 @@ +template Foo (T, U) +{ + class Bar { } + + T foo(T t, U u) { + } + + T abc; + + typedef T* FooType; + typedef Tte** FooType0; + typedef int* FooType1; + typedef const char FooType2; +} + +alias Foo!(int, char) f; +f.Bar b; +f.foo(1, 2); +f.abc = 3; + +to!string(10.0); +TFoo!int.t x; + +class Abc (T) +{ + T t; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40020-funcfunc.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40020-funcfunc.d new file mode 100644 index 00000000..de673e78 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40020-funcfunc.d @@ -0,0 +1,5 @@ +int main() +{ + mWriter("class Clst_"c)(cluster.getChild(HO_SHORT_NAME).getText())(" : Cluster {"c).newline; +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40021-tst01.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40021-tst01.d new file mode 100644 index 00000000..e19c7c8e --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40021-tst01.d @@ -0,0 +1,25 @@ +package void writeRegister(int aRegisterOffset, ushort aValue) +in +{ + assert(aRegisterOffset >= 0); + assert(aRegisterOffset < IMAGE_SIZE); +} +body { + int idx = aRegisterOffset / 2; + mMemCache[idx] = aValue; + uint readback; + uint st; + uint st2; + volatile { + mMemImage[idx] = aValue; + //readback = (cast(uint*)mMemImage.ptr)[ idx/2 ]; + //st = mMemImage[ 0x28/2 ]; + //st2 = mMemImage[ 0x2A/2 ]; + } + //if( aValue != readback ) + { + //debug(IRQ) writefln( "writeRegister %04x, %04x", aRegisterOffset, aValue); + } + // comment +} +// diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40022-tst02.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40022-tst02.d new file mode 100644 index 00000000..aa138a86 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40022-tst02.d @@ -0,0 +1,30 @@ +package static ushort calcHeaderCrc(bool aStartupFrame, bool aSyncFrame, ushort aFrameId, ushort aPayloadWords) { + uint crcData = aPayloadWords; + + crcData |= (aFrameId << 7); + + if (aSyncFrame) { + crcData |= BIT_19; + } + + if (aStartupFrame) { + crcData |= BIT_18; + } + + ushort crc = 0x1a; + const ushort table[16] = [ + 0x0000, 0x0385, 0x070A, 0x048F, + 0x0591, 0x0614, 0x029B, 0x011E, + 0x00A7, 0x0322, 0x07AD, 0x0428, + 0x0536, 0x06B3, 0x023C, 0x01B9 + ]; + + for (int i = 0; i < 5; ++i) { + if (i != 0) { + crcData <<= 4; + } + crc = ((crc << 4) & 0x7FF) ^ table[((crc >> 7) ^ (crcData >> 16)) & 0x0F]; + } + + return(crc); +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40023-bug-indent.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40023-bug-indent.d new file mode 100644 index 00000000..6071604d --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40023-bug-indent.d @@ -0,0 +1,39 @@ +class TemplatedClass(T) {} +class TemplatedClass2(T, U) {} + +class Axxxxxxxxxxxxxxxx { + alias A = int *; + void f() + { + } +} + +class C +{ + //--------------| <= (1) - non first col comment -> indent + Axxxxxxxxxxxxxxxx.A createAssignment() + { + return(null); + } + void func2(Axxxxxxxxxxxxxxxx[] container) + { + foreach (v; container) + { + v.f(); + } + } + + // | <= (2) + void func3(TemplatedClass!int aValue) + { + } + + void func4(TemplatedClass2!(int, int) b) + { + } +} + +int main() +{ + return 0; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40024-tst03.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40024-tst03.d new file mode 100644 index 00000000..2344510d --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40024-tst03.d @@ -0,0 +1,152 @@ +import std.stdio; + +void foo() +{ + float f = x % y; + double d = x % y; + real r = x % y; + + result = (x < y); // false if x or y is nan + assert(e == 0); + int array[17]; + + array[] = value; + int array[17]; + + for (i = 0; i < array.length; i++) + func(array[i]); + int array[17]; + + foreach (int value; array) + func(value); + int[] array; + + array.length = array.length + 1; + array[array.length - 1] = x; + char[] s1; + char[] s2; + char[] s; + + s = s1 ~ s2; + s ~= "hello"; + + + writefln("Calling all cars %s times!", ntimes); + Louter: + for (i = 0; i < 10; i++) + { + for (j = 0; j < 10; j++) + { + if (j == 3) + break Louter; + if (j == 4) + continue Louter; + } + } + // break Louter goes here + typedef bit bHandle; + typedef int iHandle = -1; + typedef void *Handle = cast(void *)(-1); + Handle h; + + h = func(); + if (h != Handle.init) + ; + char[] string = "hello"; + + if (string < "betty") + ; + int *p = address; + + volatile { i = *p; } + + char[] ml = "This text spans +multiple +lines +"; +} + +void dostring(char[] s) +{ + switch (s) + { + case "hello":; + + case "goodbye":; + + case "maybe":; + + default:; + } +} + +struct ABC +{ + int z; // z is aligned to the default + + align (1) int x; // x is byte aligned + align (4) + { + ... // declarations in {} are dword aligned + } + align (2) : // switch to word alignment from here on + + int y; // y is word aligned +} + +struct Foo +{ + int i; + union + { + struct { int x; long y; } + char *p; + } +} + +struct Foo { int x; int y; } // note there is no terminating ; +Foo foo; + + +struct Foo { int x; int y; } + +off = Foo.y.offsetof; + +union U { int a; long b; } +U x = { a:5 }; + +struct S { int a; int b; } +S x = { b:3, a:5 }; + +int[3] a = [ 3, 2, 0 ]; +int[3] a = [ 3, 2 ]; // unsupplied initializers are 0, just like in C +int[3] a = [ 2:0, 0:3, 1:2 ]; +int[3] a = [ 2:0, 0:3, 2 ]; // if not supplied, the index is the + // previous one plus one. + +enum color { black, red, green } +int[3] c = [ black:3, green:2, red:5 ]; + +char[] file = `c:\root\file.c`; +char[] quoteString = \" r"[^\\]*(\\.[^\\]*)*" \"; + +char[] hello = "hello world" \n; +char[] foo_ascii = "hello"; // string is taken to be ascii +wchar[] foo_wchar = "hello"; // string is taken to be wchar + +enum COLORS { red, blue, green }; + +char[][COLORS.max + 1] cstring = [ + COLORS.red : "red", + COLORS.blue : "blue", + COLORS.green : "green", +]; + +const ushort table1[16] = [ + 0x00A7, 0x0322, 0x07AD, 0x0428, + 0x0536, 0x06B3, 0x023C, 0x01B9 +]; + +const ushort table2[16] = [ 0x0000, 0x0385, 0x070A, 0x048F, + 0x0536, 0x06B3, 0x023C, 0x01B9]; + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40025-tst03.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40025-tst03.d new file mode 100644 index 00000000..15811ebc --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40025-tst03.d @@ -0,0 +1,157 @@ +import std.stdio; + +void foo() +{ + float f = x % y; + double d = x % y; + real r = x % y; + + result = (x < y); // false if x or y is nan + assert(e == 0); + int array[ 17 ]; + + array[] = value; + int array[ 17 ]; + + for (i = 0; i < array.length; i++) + func(array[ i ]); + int array[ 17 ]; + + foreach (int value; array) + func(value); + int[] array; + + array.length = array.length + 1; + array[ array.length - 1 ] = x; + char[] s1; + char[] s2; + char[] s; + + s = s1 ~ s2; + s ~= "hello"; + + + writefln("Calling all cars %s times!", ntimes); + Louter: + for (i = 0; i < 10; i++) + { + for (j = 0; j < 10; j++) + { + if (j == 3) + break Louter; + if (j == 4) + continue Louter; + } + } + // break Louter goes here + typedef bit bHandle; + typedef int iHandle = -1; + typedef void *Handle = cast(void *)(-1); + Handle h; + + h = func(); + if (h != Handle.init) + ; + char[] string = "hello"; + + if (string < "betty") + ; + int *p = address; + + volatile { i = *p; } + + char[] ml = "This text spans +multiple +lines +"; +} + +void dostring(char[] s) +{ + switch (s) + { + case "hello":; + + case "goodbye":; + + case "maybe":; + + default:; + } +} + +struct ABC +{ + int z; // z is aligned to the default + + align (1) int x; // x is byte aligned + align (4) + { + ... // declarations in {} are dword aligned + } + align (2) : // switch to word alignment from here on + + int y; // y is word aligned +} + +struct Foo +{ + int i; + union + { + struct { int x; long y; } + char *p; + } +} + +struct Foo { int x; int y; } // note there is no terminating ; +Foo foo; + + +struct Foo { int x; int y; } + +off = Foo.y.offsetof; + +union U { int a; long b; } +U x = { a:5 }; + +struct S { int a; int b; } +S x = { b:3, a:5 }; + +int[ 3 ] a = [ 3, 2, 0 ]; +int[ 3 ] a = [ 3, 2 ]; // unsupplied initializers are 0, just like in C +int[ 3 ] a = [ 2:0, 0:3, 1:2 ]; +int[ 3 ] a = [ 2:0, 0:3, 2 ]; // if not supplied, the index is the + // previous one plus one. + +enum color { black, red, green } +int[ 3 ] c = [ black:3, green:2, red:5 ]; + +char[] file = `c:\root\file.c`; +char[] quoteString = \" r"[^\\]*(\\.[^\\]*)*" \"; + +char[] hello = "hello world" \n; +char[] foo_ascii = "hello"; // string is taken to be ascii +wchar[] foo_wchar = "hello"; // string is taken to be wchar + +enum COLORS { red, blue, green }; + +char[][ COLORS.max + 1 ] cstring = +[ + COLORS.red:"red", + COLORS.blue:"blue", + COLORS.green:"green", +]; + +const ushort table1[ 16 ] = +[ + 0x00A7, 0x0322, 0x07AD, 0x0428, + 0x0536, 0x06B3, 0x023C, 0x01B9 +]; + +const ushort table2[ 16 ] = +[ + 0x0000, 0x0385, 0x070A, 0x048F, + 0x0536, 0x06B3, 0x023C, 0x01B9 +]; + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40026-wysiwyg_strings.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40026-wysiwyg_strings.d new file mode 100644 index 00000000..cfdec32a --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40026-wysiwyg_strings.d @@ -0,0 +1,9 @@ +auto s = `\`; +auto t = `\a +b +`; + +auto u = r"\"; +auto v = r"\a +b +";
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40027-static_if_in_struct.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40027-static_if_in_struct.d new file mode 100644 index 00000000..be936335 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40027-static_if_in_struct.d @@ -0,0 +1,5 @@ +struct Widget {
+ static if (true)
+ void fun() {
+ }
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40030-delegate.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40030-delegate.d new file mode 100644 index 00000000..5f7beceb --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40030-delegate.d @@ -0,0 +1,22 @@ +module er; + +void delegate(ubyte[] a) TSender; +bool delegate(ushort a) TVerifier; +typedef ushort TAddr; + +public void delegate(ubyte[] a) TSender; +public bool delegate(ushort a) TVerifier; +public typedef ushort TAddr; + +void delegate() dg; +dg = { + int y; +}; + +int opApply(int delegate(inout Type[, ...]) dg); + +void main() +{ + assert(findIf("bcecg", (int x) { return x == 'a'; }) == 5); +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40035-enum.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40035-enum.d new file mode 100644 index 00000000..24d0ef63 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40035-enum.d @@ -0,0 +1,7 @@ +/* sized enum like in C# */ +enum Metrics : int +{ + SM_CXSCREEN = 0, + SM_CYSCREEN, + SM_CXVSCROLL, +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40040-sort_import.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40040-sort_import.d new file mode 100644 index 00000000..db26c1e4 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40040-sort_import.d @@ -0,0 +1,19 @@ +// should be ddd, eee, fff +import ddd; +import eee; +import fff; + +// should be aaa, ccc +import aaa; +import ccc; +// should be just bbb +import bbb; + +// should not change these, as it can't handle multi-line imports +private import mango.ccc; +private import mango.bbb, + mango.aaa; + +void foo(); + + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40050-strings.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40050-strings.d new file mode 100644 index 00000000..4964ad7a --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40050-strings.d @@ -0,0 +1,32 @@ + +/* This file goes over all the various string formats for D */ + +int foo(int bar) +{ + char[] a; + char b; + + a = r"WYSIWYG"; + a = `WYSIWYG`; + b = 'c'; + a = x"12 34 5678 90"; + a = "This\nis a \"test\""; + a = \' ~ \" ~ \? ~ \\ ~ \a ~ \b ~ \f ~ \n ~ \r ~ \t ~ \v; + a = \x1B ~ \0 ~ \74 ~ \123; + a = \u1234 ~ \U12345678; + a = \& ~ 'a'; + a = "Another" " " "Test"; + + /+ test back to back EscapeSequences +/ + a = \r\n\xff\&\u1234; + + a = "char"c; + a = "wchar"w; + a = "dchar"d; + + /* + * multi line string + */ + a = r"Line 1 + line 2"; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40051-numbers.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40051-numbers.d new file mode 100644 index 00000000..72d55727 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40051-numbers.d @@ -0,0 +1,46 @@ + +/* This file goes over all the various number formats for D */ + +int foo(int bar) +{ + int a; + + /* + * Interger Literals + */ + + /* Suffixes */ + a = 0L + 123U + 345u + 456Lu + 567LU + 678UL + 789_uL; + + /* Decimal */ + a = 0 + 123456 + 123_456 + 1_2_3_4_5_6; + + /* Binary */ + a = 0b1010101 + 0B1001; + + /* Octal */ + a = 01234567_ + 07_6_5_2; + + /* Hexadecimal */ + a = 0x1234567890abcdefABCDEF_ + 0X7_6_5_2; + + float b; + real c; + ifloat d; + ireal e; + + /* Floats: float [FloatSuffix] [ImaginarySuffix] */ + + /* HexFloat */ + b = 0xabc.defp-1024 + 0x.defP-64 + 0x123p+32 + 0x123P+16 + 0x123p1024; + d = 0x123p45 + 0x234.fi + 0. + .3f; + e = 3 + 5i; + e = 3.4 + 5.6i; +} + +/* test '..' ranges */ +void main() +{ + char[] c = "kkkkkkkkkkkkkkkkkkkkk"; + writefln("%s", c[2 .. 3]); +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40052-numbers.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40052-numbers.d new file mode 100644 index 00000000..8cf51f29 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40052-numbers.d @@ -0,0 +1,43 @@ +/* This file goes over all the various number formats for D */ + +int foo(int bar) { + int a; + + /* + * Interger Literals + */ + + /* Suffixes */ + a = 0L + 123U + 345u + 456Lu + 567LU + 678UL + 789_uL; + + /* Decimal */ + a = 0 + 123456 + 123_456 + 1_2_3_4_5_6; + + /* Binary */ + a = 0b1010101 + 0B1001; + + /* Octal */ + a = 01234567_ + 07_6_5_2; + + /* Hexadecimal */ + a = 0x1234567890abcdefABCDEF_ + 0X7_6_5_2; + + float b; + real c; + ifloat d; + ireal e; + + /* Floats: float [FloatSuffix] [ImaginarySuffix] */ + + /* HexFloat */ + b = 0xabc.defp-1024 + 0x.defP-64 + 0x123p+32 + 0x123P+16 + 0x123p1024; + d = 0x123p45 + 0x234.fi + 0. + .3f; + e = 3 + 5i; + e = 3.4 + 5.6i; +} + +/* test '..' ranges */ +void main() { + char[] c = "kkkkkkkkkkkkkkkkkkkkk"; + writefln("%s", c[2..3]); +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40060-casts.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40060-casts.d new file mode 100644 index 00000000..b1d6b50b --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40060-casts.d @@ -0,0 +1,13 @@ +void foo(int a) +{ + char ch; + + ch = cast(char)a; + ch = cast(char)45; + ch = (char)a; // not a d cast + ch = (int) 45; + ch = cast(foo)*bar; + ch = cast(foo)-bar; + ch = cast(foo)+45; + ch = cast(foo)&45; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40061-const.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40061-const.d new file mode 100644 index 00000000..8277f0c1 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40061-const.d @@ -0,0 +1,11 @@ +// hello +A b() +{ + return null; +} + +const(C) d() +{ + return null; +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40070-d_sp_paren.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40070-d_sp_paren.d new file mode 100644 index 00000000..cc38daae --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40070-d_sp_paren.d @@ -0,0 +1,23 @@ +version(unittest) { + import foo; +} + +void main() { + scope(exit) { + foo(); + } + + scope(success) suckit(); + + scope f = new Foo(); + if (foo) + { + } + + try { + throw(e); + } + catch(Exception e) { + } +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40080-static_if.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40080-static_if.d new file mode 100644 index 00000000..0eb3a1a8 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40080-static_if.d @@ -0,0 +1,11 @@ +ClLinearExpression opBinary(string op) (double constant) +{ + static if (op == "+") + return new ClLinearExpression(this, 1, constant); + else static if (op == "-") + return new ClLinearExpression(this, 1, -constant); + else static if (op == "*") + return new ClLinearExpression(this, constant, 0); + else static if (op == "/") + return new ClLinearExpression(this, 1.0 / constant, 0); +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40090-square_indent_tab.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40090-square_indent_tab.d new file mode 100644 index 00000000..e9657860 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40090-square_indent_tab.d @@ -0,0 +1,25 @@ +auto getOperatorsMap() { + return [ + "/" : TokenType.Slash, + "/=" : TokenType.SlashAssign, + "." : TokenType.Dot, + ".." : TokenType.DoubleDot, + "..." : TokenType.TripleDot, + "&" : TokenType.Ampersand, + "&=" : TokenType.AmpersandAssign, + "&&" : TokenType.DoubleAmpersand, + "|" : TokenType.Pipe, + "|=" : TokenType.PipeAssign, + "||" : TokenType.DoublePipe, + "-" : TokenType.Minus, + "-=" : TokenType.MinusAssign, + "--" : TokenType.DoubleMinus, + "+" : TokenType.Plus, + "+=" : TokenType.PlusAssign, + "++" : TokenType.DoublePlus, + "<" : TokenType.Less, + "<=" : TokenType.LessAssign, + "<<" : TokenType.DoubleLess + ]; +} + diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40100-1438.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40100-1438.d new file mode 100644 index 00000000..66c47d3a --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40100-1438.d @@ -0,0 +1 @@ +invariant(1 <= day && day <= 31); diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40201-invariant.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40201-invariant.d new file mode 100644 index 00000000..3da6240f --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40201-invariant.d @@ -0,0 +1 @@ +invariant (C)c; diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40300-extern_.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40300-extern_.d new file mode 100644 index 00000000..40131d6d --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40300-extern_.d @@ -0,0 +1,6 @@ +extern(D) : void func(); + +void x() +{ + int xx; +} diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40400-vbraces000.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40400-vbraces000.d new file mode 100644 index 00000000..616bb259 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40400-vbraces000.d @@ -0,0 +1,15 @@ +struct A
+{
+ static if (true)
+ void f() {
+ }
+}
+struct B
+{
+ static if(true) {
+ int a;
+ }
+ else{
+ int e;
+ }
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40401-vbraces001.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40401-vbraces001.d new file mode 100644 index 00000000..6d7e96f6 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40401-vbraces001.d @@ -0,0 +1,9 @@ +module x;
+static if (1)
+ void fun()
+ {
+ }
+static if (1)
+ void gun()
+ {
+ }
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40402-vbraces002.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40402-vbraces002.d new file mode 100644 index 00000000..c966d140 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40402-vbraces002.d @@ -0,0 +1,23 @@ +int super_fun(bool a, bool b, bool c, bool d)
+{
+ int i = 6;
+ static if (true)
+ while (true)
+ if(b) {
+ return 1;
+ }
+ else if (c) {
+ while (true)
+ if(d) {
+ return 2;
+ }
+ else{
+ while (true)
+ if(a)
+ return 3;
+ }
+ }
+ while (d)
+ return 4;
+ return 1;
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40403-template_use.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40403-template_use.d new file mode 100644 index 00000000..94cdbf6b --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40403-template_use.d @@ -0,0 +1,2 @@ +auto x = a!"23" + a!`23` + a!`2 +3` + a!23 + a!23.23; diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40500-template_spacing000.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40500-template_spacing000.d new file mode 100644 index 00000000..627ca266 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40500-template_spacing000.d @@ -0,0 +1,12 @@ +void fun() {
+ if (something(a1, a2))
+ return;
+ if (something!a1)
+ return;
+ if (something!(a1, a2) )
+ return;
+ if (something!(a1, a2).Ptr)
+ return;
+ if (something!a1.Ptr)
+ return;
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40501-template_spacing001.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40501-template_spacing001.d new file mode 100644 index 00000000..dc3242ff --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40501-template_spacing001.d @@ -0,0 +1,9 @@ +void func0(TemplatedClass2!(int, int)b){
+}
+
+void func1(TemplatedClass2!(int, int)b){
+}
+
+
+void func2(TemplatedClass!int b){
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40502-template_spacing001.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40502-template_spacing001.d new file mode 100644 index 00000000..3c238a1f --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40502-template_spacing001.d @@ -0,0 +1,9 @@ +void func0(TemplatedClass2!(int, int) b){
+}
+
+void func1(TemplatedClass2!(int, int) b){
+}
+
+
+void func2(TemplatedClass!int b){
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40503-template_spacing001.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40503-template_spacing001.d new file mode 100644 index 00000000..010cbe07 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40503-template_spacing001.d @@ -0,0 +1,9 @@ +void func0(TemplatedClass2!(int, int) b){
+}
+
+void func1(TemplatedClass2!(int, int) b){
+}
+
+
+void func2(TemplatedClass!int b){
+}
\ No newline at end of file diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40504-type_spacing000.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40504-type_spacing000.d new file mode 100644 index 00000000..1e47f131 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40504-type_spacing000.d @@ -0,0 +1,2 @@ +alias jhash hash;
+alias Foo!(int, char) f;
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40505-type_spacing000.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40505-type_spacing000.d new file mode 100644 index 00000000..1e47f131 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40505-type_spacing000.d @@ -0,0 +1,2 @@ +alias jhash hash;
+alias Foo!(int, char) f;
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40506-type_spacing000.d b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40506-type_spacing000.d new file mode 100644 index 00000000..e11e545b --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/tests/expected/d/40506-type_spacing000.d @@ -0,0 +1,2 @@ +alias jhash hash;
+alias Foo!(int, char) f;
|