Commit 8bbfda4c authored by Vysheng's avatar Vysheng

files for new version

parent 1dad2e89
/*
This file is part of VK/KittenPHP-DB-Engine Library.
VK/KittenPHP-DB-Engine Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with VK/KittenPHP-DB-Engine Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrei Lopatin
2012 Anton Maydell
*/
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "crc32.h"
unsigned int crc32_table[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
unsigned int crc32_table2[256] =
{
0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3,
0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7,
0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb,
0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf,
0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496,
0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a,
0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e,
0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761,
0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69,
0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d,
0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530,
0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034,
0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c,
0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6,
0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2,
0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce,
0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97,
0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93,
0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f,
0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b,
0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60,
0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c,
0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768,
0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35,
0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d,
0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539,
0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88,
0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c,
0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484,
0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9,
0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd,
0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1,
0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a,
0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e,
0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522,
0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026,
0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f,
0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773,
0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277,
0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d,
0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85,
0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81,
0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc,
0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8,
0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0,
0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f,
0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b,
0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27,
0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e,
0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a,
0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876,
0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72,
};
unsigned int crc32_table1[256] =
{
0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59,
0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685,
0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1,
0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d,
0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5,
0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91,
0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d,
0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9,
0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901,
0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd,
0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9,
0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315,
0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad,
0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399,
0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45,
0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221,
0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9,
0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835,
0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151,
0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d,
0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5,
0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1,
0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d,
0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609,
0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1,
0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d,
0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9,
0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05,
0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd,
0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9,
0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75,
0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711,
0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339,
0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5,
0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281,
0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d,
0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895,
0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1,
0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d,
0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819,
0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1,
0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d,
0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69,
0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5,
0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d,
0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9,
0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625,
0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41,
0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89,
0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555,
0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31,
0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed,
};
unsigned int crc32_table0[256] = {
0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee,
0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9,
0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701,
0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056,
0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26,
0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e,
0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9,
0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0,
0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f,
0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68,
0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f,
0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018,
0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7,
0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3,
0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084,
0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c,
0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c,
0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b,
0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3,
0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4,
0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba,
0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002,
0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755,
0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72,
0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d,
0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca,
0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5,
0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82,
0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d,
0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a,
0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d,
0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5,
0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb,
0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc,
0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04,
0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953,
0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623,
0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b,
0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc,
0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8,
0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907,
0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50,
0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677,
0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120,
0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf,
0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6,
0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981,
0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639,
0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949,
0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e,
0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6,
0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1,
};
unsigned crc32_partial_old (const void *data, int len, unsigned crc) {
const char *p = data;
for (; len > 0; len--) {
crc = crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
}
return crc;
}
/*
unsigned crc32_partial_fast (const void *data, int len, unsigned crc) {
const int *p = (const int *) data;
int x;
for (x = (len >> 2); x > 0; x--) {
crc ^= *p++;
crc = crc32_table0[crc & 0xff] ^ crc32_table1[(crc & 0xff00) >> 8] ^ crc32_table2[(crc & 0xff0000) >> 16] ^ crc32_table[crc >> 24];
}
const char *q = (const char *) p;
switch (len & 3) {
case 3:
crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
case 2:
crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
case 1:
crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
}
return crc;
}
*/
unsigned crc32_partial (const void *data, int len, unsigned crc) {
const int *p = (const int *) data;
int x;
#define DO_ONE(v) crc ^= v; crc = crc32_table0[crc & 0xff] ^ crc32_table1[(crc & 0xff00) >> 8] ^ crc32_table2[(crc & 0xff0000) >> 16] ^ crc32_table[crc >> 24];
#define DO_FOUR(p) DO_ONE((p)[0]); DO_ONE((p)[1]); DO_ONE((p)[2]); DO_ONE((p)[3]);
for (x = (len >> 5); x > 0; x--) {
DO_FOUR (p);
DO_FOUR (p + 4);
p += 8;
}
if (len & 16) {
DO_FOUR (p);
p += 4;
}
if (len & 8) {
DO_ONE (p[0]);
DO_ONE (p[1]);
p += 2;
}
if (len & 4) {
DO_ONE (*p++);
}
/*
for (x = (len >> 2) & 7; x > 0; x--) {
DO_ONE (*p++);
}
*/
#undef DO_ONE
#undef DO_FOUR
const char *q = (const char *) p;
if (len & 2) {
crc = crc32_table[(crc ^ q[0]) & 0xff] ^ (crc >> 8);
crc = crc32_table[(crc ^ q[1]) & 0xff] ^ (crc >> 8);
q += 2;
}
if (len & 1) {
crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
}
return crc;
}
unsigned compute_crc32 (const void *data, int len) {
return crc32_partial (data, len, -1) ^ -1;
}
unsigned long long crc64_table[256] = {
0x0000000000000000LL, 0xb32e4cbe03a75f6fLL, 0xf4843657a840a05bLL, 0x47aa7ae9abe7ff34LL,
0x7bd0c384ff8f5e33LL, 0xc8fe8f3afc28015cLL, 0x8f54f5d357cffe68LL, 0x3c7ab96d5468a107LL,
0xf7a18709ff1ebc66LL, 0x448fcbb7fcb9e309LL, 0x0325b15e575e1c3dLL, 0xb00bfde054f94352LL,
0x8c71448d0091e255LL, 0x3f5f08330336bd3aLL, 0x78f572daa8d1420eLL, 0xcbdb3e64ab761d61LL,
0x7d9ba13851336649LL, 0xceb5ed8652943926LL, 0x891f976ff973c612LL, 0x3a31dbd1fad4997dLL,
0x064b62bcaebc387aLL, 0xb5652e02ad1b6715LL, 0xf2cf54eb06fc9821LL, 0x41e11855055bc74eLL,
0x8a3a2631ae2dda2fLL, 0x39146a8fad8a8540LL, 0x7ebe1066066d7a74LL, 0xcd905cd805ca251bLL,
0xf1eae5b551a2841cLL, 0x42c4a90b5205db73LL, 0x056ed3e2f9e22447LL, 0xb6409f5cfa457b28LL,
0xfb374270a266cc92LL, 0x48190ecea1c193fdLL, 0x0fb374270a266cc9LL, 0xbc9d3899098133a6LL,
0x80e781f45de992a1LL, 0x33c9cd4a5e4ecdceLL, 0x7463b7a3f5a932faLL, 0xc74dfb1df60e6d95LL,
0x0c96c5795d7870f4LL, 0xbfb889c75edf2f9bLL, 0xf812f32ef538d0afLL, 0x4b3cbf90f69f8fc0LL,
0x774606fda2f72ec7LL, 0xc4684a43a15071a8LL, 0x83c230aa0ab78e9cLL, 0x30ec7c140910d1f3LL,
0x86ace348f355aadbLL, 0x3582aff6f0f2f5b4LL, 0x7228d51f5b150a80LL, 0xc10699a158b255efLL,
0xfd7c20cc0cdaf4e8LL, 0x4e526c720f7dab87LL, 0x09f8169ba49a54b3LL, 0xbad65a25a73d0bdcLL,
0x710d64410c4b16bdLL, 0xc22328ff0fec49d2LL, 0x85895216a40bb6e6LL, 0x36a71ea8a7ace989LL,
0x0adda7c5f3c4488eLL, 0xb9f3eb7bf06317e1LL, 0xfe5991925b84e8d5LL, 0x4d77dd2c5823b7baLL,
0x64b62bcaebc387a1LL, 0xd7986774e864d8ceLL, 0x90321d9d438327faLL, 0x231c512340247895LL,
0x1f66e84e144cd992LL, 0xac48a4f017eb86fdLL, 0xebe2de19bc0c79c9LL, 0x58cc92a7bfab26a6LL,
0x9317acc314dd3bc7LL, 0x2039e07d177a64a8LL, 0x67939a94bc9d9b9cLL, 0xd4bdd62abf3ac4f3LL,
0xe8c76f47eb5265f4LL, 0x5be923f9e8f53a9bLL, 0x1c4359104312c5afLL, 0xaf6d15ae40b59ac0LL,
0x192d8af2baf0e1e8LL, 0xaa03c64cb957be87LL, 0xeda9bca512b041b3LL, 0x5e87f01b11171edcLL,
0x62fd4976457fbfdbLL, 0xd1d305c846d8e0b4LL, 0x96797f21ed3f1f80LL, 0x2557339fee9840efLL,
0xee8c0dfb45ee5d8eLL, 0x5da24145464902e1LL, 0x1a083bacedaefdd5LL, 0xa9267712ee09a2baLL,
0x955cce7fba6103bdLL, 0x267282c1b9c65cd2LL, 0x61d8f8281221a3e6LL, 0xd2f6b4961186fc89LL,
0x9f8169ba49a54b33LL, 0x2caf25044a02145cLL, 0x6b055fede1e5eb68LL, 0xd82b1353e242b407LL,
0xe451aa3eb62a1500LL, 0x577fe680b58d4a6fLL, 0x10d59c691e6ab55bLL, 0xa3fbd0d71dcdea34LL,
0x6820eeb3b6bbf755LL, 0xdb0ea20db51ca83aLL, 0x9ca4d8e41efb570eLL, 0x2f8a945a1d5c0861LL,
0x13f02d374934a966LL, 0xa0de61894a93f609LL, 0xe7741b60e174093dLL, 0x545a57dee2d35652LL,
0xe21ac88218962d7aLL, 0x5134843c1b317215LL, 0x169efed5b0d68d21LL, 0xa5b0b26bb371d24eLL,
0x99ca0b06e7197349LL, 0x2ae447b8e4be2c26LL, 0x6d4e3d514f59d312LL, 0xde6071ef4cfe8c7dLL,
0x15bb4f8be788911cLL, 0xa6950335e42fce73LL, 0xe13f79dc4fc83147LL, 0x521135624c6f6e28LL,
0x6e6b8c0f1807cf2fLL, 0xdd45c0b11ba09040LL, 0x9aefba58b0476f74LL, 0x29c1f6e6b3e0301bLL,
0xc96c5795d7870f42LL, 0x7a421b2bd420502dLL, 0x3de861c27fc7af19LL, 0x8ec62d7c7c60f076LL,
0xb2bc941128085171LL, 0x0192d8af2baf0e1eLL, 0x4638a2468048f12aLL, 0xf516eef883efae45LL,
0x3ecdd09c2899b324LL, 0x8de39c222b3eec4bLL, 0xca49e6cb80d9137fLL, 0x7967aa75837e4c10LL,
0x451d1318d716ed17LL, 0xf6335fa6d4b1b278LL, 0xb199254f7f564d4cLL, 0x02b769f17cf11223LL,
0xb4f7f6ad86b4690bLL, 0x07d9ba1385133664LL, 0x4073c0fa2ef4c950LL, 0xf35d8c442d53963fLL,
0xcf273529793b3738LL, 0x7c0979977a9c6857LL, 0x3ba3037ed17b9763LL, 0x888d4fc0d2dcc80cLL,
0x435671a479aad56dLL, 0xf0783d1a7a0d8a02LL, 0xb7d247f3d1ea7536LL, 0x04fc0b4dd24d2a59LL,
0x3886b22086258b5eLL, 0x8ba8fe9e8582d431LL, 0xcc0284772e652b05LL, 0x7f2cc8c92dc2746aLL,
0x325b15e575e1c3d0LL, 0x8175595b76469cbfLL, 0xc6df23b2dda1638bLL, 0x75f16f0cde063ce4LL,
0x498bd6618a6e9de3LL, 0xfaa59adf89c9c28cLL, 0xbd0fe036222e3db8LL, 0x0e21ac88218962d7LL,
0xc5fa92ec8aff7fb6LL, 0x76d4de52895820d9LL, 0x317ea4bb22bfdfedLL, 0x8250e80521188082LL,
0xbe2a516875702185LL, 0x0d041dd676d77eeaLL, 0x4aae673fdd3081deLL, 0xf9802b81de97deb1LL,
0x4fc0b4dd24d2a599LL, 0xfceef8632775faf6LL, 0xbb44828a8c9205c2LL, 0x086ace348f355aadLL,
0x34107759db5dfbaaLL, 0x873e3be7d8faa4c5LL, 0xc094410e731d5bf1LL, 0x73ba0db070ba049eLL,
0xb86133d4dbcc19ffLL, 0x0b4f7f6ad86b4690LL, 0x4ce50583738cb9a4LL, 0xffcb493d702be6cbLL,
0xc3b1f050244347ccLL, 0x709fbcee27e418a3LL, 0x3735c6078c03e797LL, 0x841b8ab98fa4b8f8LL,
0xadda7c5f3c4488e3LL, 0x1ef430e13fe3d78cLL, 0x595e4a08940428b8LL, 0xea7006b697a377d7LL,
0xd60abfdbc3cbd6d0LL, 0x6524f365c06c89bfLL, 0x228e898c6b8b768bLL, 0x91a0c532682c29e4LL,
0x5a7bfb56c35a3485LL, 0xe955b7e8c0fd6beaLL, 0xaeffcd016b1a94deLL, 0x1dd181bf68bdcbb1LL,
0x21ab38d23cd56ab6LL, 0x9285746c3f7235d9LL, 0xd52f0e859495caedLL, 0x6601423b97329582LL,
0xd041dd676d77eeaaLL, 0x636f91d96ed0b1c5LL, 0x24c5eb30c5374ef1LL, 0x97eba78ec690119eLL,
0xab911ee392f8b099LL, 0x18bf525d915feff6LL, 0x5f1528b43ab810c2LL, 0xec3b640a391f4fadLL,
0x27e05a6e926952ccLL, 0x94ce16d091ce0da3LL, 0xd3646c393a29f297LL, 0x604a2087398eadf8LL,
0x5c3099ea6de60cffLL, 0xef1ed5546e415390LL, 0xa8b4afbdc5a6aca4LL, 0x1b9ae303c601f3cbLL,
0x56ed3e2f9e224471LL, 0xe5c372919d851b1eLL, 0xa26908783662e42aLL, 0x114744c635c5bb45LL,
0x2d3dfdab61ad1a42LL, 0x9e13b115620a452dLL, 0xd9b9cbfcc9edba19LL, 0x6a978742ca4ae576LL,
0xa14cb926613cf817LL, 0x1262f598629ba778LL, 0x55c88f71c97c584cLL, 0xe6e6c3cfcadb0723LL,
0xda9c7aa29eb3a624LL, 0x69b2361c9d14f94bLL, 0x2e184cf536f3067fLL, 0x9d36004b35545910LL,
0x2b769f17cf112238LL, 0x9858d3a9ccb67d57LL, 0xdff2a94067518263LL, 0x6cdce5fe64f6dd0cLL,
0x50a65c93309e7c0bLL, 0xe388102d33392364LL, 0xa4226ac498dedc50LL, 0x170c267a9b79833fLL,
0xdcd7181e300f9e5eLL, 0x6ff954a033a8c131LL, 0x28532e49984f3e05LL, 0x9b7d62f79be8616aLL,
0xa707db9acf80c06dLL, 0x14299724cc279f02LL, 0x5383edcd67c06036LL, 0xe0ada17364673f59LL
};
unsigned long long crc64_partial (const void *data, int len, unsigned long long crc) {
const char *p = data;
for (; len > 0; len--) {
crc = crc64_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
}
return crc;
}
unsigned long long crc64 (const void *data, int len) {
return crc64_partial (data, len, -1LL) ^ -1LL;
}
static unsigned gf32_matrix_times (unsigned *matrix, unsigned vector) {
unsigned sum = 0;
while (vector) {
if (vector & 1) {
sum ^= *matrix;
}
vector >>= 1;
matrix++;
}
return sum;
}
static void gf32_matrix_square (unsigned *square, unsigned *matrix) {
int n = 0;
do {
square[n] = gf32_matrix_times (matrix, matrix[n]);
} while (++n < 32);
}
unsigned compute_crc32_combine (unsigned crc1, unsigned crc2, int len2) {
static int power_buf_initialized = 0;
static unsigned power_buf[1024];
int n;
/* degenerate case (also disallow negative lengths) */
if (len2 <= 0) {
return crc1;
}
if (!power_buf_initialized) {
power_buf[0] = 0xedb88320UL;
for (n = 0; n < 31; n++) {
power_buf[n+1] = 1U << n;
}
for (n = 1; n < 32; n++) {
gf32_matrix_square (power_buf + (n << 5), power_buf + ((n - 1) << 5));
}
power_buf_initialized = 1;
}
unsigned int *p = power_buf + 64;
do {
p += 32;
if (len2 & 1) {
crc1 = gf32_matrix_times (p, crc1);
}
len2 >>= 1;
} while (len2);
return crc1 ^ crc2;
}
/********************************* crc32 repair ************************/
struct fcb_table_entry {
unsigned p; //zeta ^ k
int i;
};
static inline unsigned gf32_mod (unsigned long long r, int high_bit) {
int j = high_bit;
for (j = high_bit; j >= 32; j--) {
if ((1ULL << j) & r) {
r ^= 0x04C11DB7ULL << (j - 32);
}
}
return (unsigned) r;
}
static unsigned gf32_mult (unsigned a, unsigned b) {
int i;
const unsigned long long m = b;
unsigned long long r = 0;
for (i = 0; i < 32; i++) {
if (a & (1U << i)) {
r ^= m << i;
}
}
return gf32_mod (r, 62);
}
static unsigned gf32_shl (unsigned int a, int shift) {
unsigned long long r = a;
r <<= shift;
return gf32_mod (r, 31 + shift);
}
static unsigned gf32_pow (unsigned a, int k) {
if (!k) { return 1; }
unsigned x = gf32_pow (gf32_mult (a, a), k >> 1);
if (k & 1) {
x = gf32_mult (x, a);
}
return x;
}
static int cmp_fcb_table_entry (const void *a, const void *b) {
const struct fcb_table_entry *x = a;
const struct fcb_table_entry *y = b;
if (x->p < y->p) { return -1; }
if (x->p > y->p) { return 1; }
if (x->i < y->i) { return -1; }
if (x->i > y->i) { return 1; }
return 0;
}
#define GROUP_SWAP(x,m,s) ((x & m) << s) | ((x & (~m)) >> s)
static unsigned revbin (unsigned x) {
x = GROUP_SWAP(x,0x55555555U,1);
x = GROUP_SWAP(x,0x33333333U,2);
x = GROUP_SWAP(x,0x0f0f0f0fU,4);
x = __builtin_bswap32 (x);
return x;
}
#undef GROUP_SWAP
static inline unsigned xmult (unsigned a) {
unsigned r = a << 1;
if (a & (1U<<31)) {
r ^= 0x04C11DB7U;
}
return r;
}
static int find_corrupted_bit (int size, unsigned d) {
int i, j;
size += 4;
d = revbin (d);
int n = size << 3;
int r = (int) (sqrt (n) + 0.5);
struct fcb_table_entry *T = calloc (r, sizeof (struct fcb_table_entry));
assert (T != NULL);
T[0].i = 0;
T[0].p = 1;
for (i = 1; i < r; i++) {
T[i].i = i;
T[i].p = xmult (T[i-1].p);
}
assert (xmult (0x82608EDB) == 1);
qsort (T, r, sizeof (T[0]), cmp_fcb_table_entry);
unsigned q = gf32_pow (0x82608EDB, r);
unsigned A[32];
for (i = 0; i < 32; i++) {
A[i] = gf32_shl (q, i);
}
unsigned x = d;
int max_j = n / r, res = -1;
for (j = 0; j <= max_j; j++) {
int a = -1, b = r;
while (b - a > 1) {
int c = ((a + b) >> 1);
if (T[c].p <= x) { a = c; } else { b = c; }
}
if (a >= 0 && T[a].p == x) {
res = T[a].i + r * j;
break;
}
x = gf32_matrix_times (A, x);
}
free (T);
return res;
}
static int repair_bit (unsigned char *input, int l, int k) {
if (k < 0) {
return -1;
}
int idx = k >> 5, bit = k & 31, i = (l - 1) - (idx - 1) * 4;
while (bit >= 8) {
i--;
bit -= 8;
}
if (i < 0) {
return -2;
}
if (i >= l) {
return -3;
}
int j = 7 - bit;
input[i] ^= 1 << j;
return 0;
}
int crc32_check_and_repair (void *input, int l, unsigned *input_crc32, int force_exit) {
unsigned computed_crc32 = compute_crc32 (input, l);
const unsigned crc32_diff = computed_crc32 ^ (*input_crc32);
if (!crc32_diff) {
return 0;
}
int k = find_corrupted_bit (l, crc32_diff);
int r = repair_bit (input, l, k);
if (!r) {
assert (compute_crc32 (input, l) == *input_crc32);
return 1;
}
if (!(crc32_diff & (crc32_diff - 1))) { /* crc32_diff is power of 2 */
*input_crc32 = computed_crc32;
return 2;
}
assert (!force_exit);
*input_crc32 = computed_crc32;
return -1;
}
/*
This file is part of VK/KittenPHP-DB-Engine Library.
VK/KittenPHP-DB-Engine Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with VK/KittenPHP-DB-Engine Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrei Lopatin
2012 Anton Maydell
*/
#ifndef __CRC32_H__
#define __CRC32_H__
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned int crc32_table[256];
unsigned crc32_partial (const void *data, int len, unsigned crc);
//unsigned crc32_partial_fast (const void *data, int len, unsigned crc);
//unsigned crc32_partial_fastest (const void *data, int len, unsigned crc);
unsigned compute_crc32 (const void *data, int len);
unsigned compute_crc32_combine (unsigned crc1, unsigned crc2, int len2);
extern unsigned long long crc64_table[256];
unsigned long long crc64_partial (const void *data, int len, unsigned long long crc);
unsigned long long crc64 (const void *data, int len);
//unsigned gf32_matrix_times (unsigned *matrix, unsigned vector);
/* crc32_check_and_repair returns
0 : Cyclic redundancy check is ok
1 : Cyclic redundancy check fails, but we fix one bit in input
2 : Cyclic redundancy check fails, but we fix one bit in input_crc32
-1 : Cyclic redundancy check fails, no repair possible.
In this case *input_crc32 will be equal crc32 (input, l)
Case force_exit == 1 (case 1, 2: kprintf call, case -1: assert fail).
*/
int crc32_check_and_repair (void *input, int l, unsigned *input_crc32, int force_exit);
#ifdef __cplusplus
}
#endif
#endif
......@@ -92,7 +92,7 @@ int get_random_bytes (unsigned char *buf, int n) {
void my_clock_gettime (int clock_id UU, struct timespec *T) {
#ifdef __MACH__
// We are ignoring MONOTONIC and hope time doesn't go back to often
// We are ignoring MONOTONIC and hope time doesn't go back too often
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
......
int ?= Int;
long ?= Long;
double ?= Double;
string ?= String;
bytes string = Bytes;
boolFalse#bc799737 = Bool;
boolTrue#997275b5 = Bool;
vector#1cb5c415 {t:Type} # [ t ] = Vector t;
error#c4b9f9bb code:int text:string = Error;
null#56730bcc = Null;
inputPeerEmpty#7f3b18ea = InputPeer;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerContact#1023dbe8 user_id:int = InputPeer;
inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
inputPeerChat#179be863 chat_id:int = InputPeer;
inputUserEmpty#b98886cf = InputUser;
inputUserSelf#f7c1b13f = InputUser;
inputUserContact#86e94f65 user_id:int = InputUser;
inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
inputMediaEmpty#9664f57f = InputMedia;
inputMediaUploadedPhoto#2dc53a7d file:InputFile = InputMedia;
inputMediaPhoto#8f2ab2ec id:InputPhoto = InputMedia;
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia;
inputMediaUploadedVideo#133ad6f6 file:InputFile duration:int w:int h:int mime_type:string = InputMedia;
inputMediaUploadedThumbVideo#9912dabf file:InputFile thumb:InputFile duration:int w:int h:int mime_type:string = InputMedia;
inputMediaVideo#7f023ae6 id:InputVideo = InputMedia;
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto;
inputChatPhoto#b2e1bf08 id:InputPhoto crop:InputPhotoCrop = InputChatPhoto;
inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
inputPhotoEmpty#1cd7bf0d = InputPhoto;
inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
inputVideoEmpty#5508ec75 = InputVideo;
inputVideo#ee579652 id:long access_hash:long = InputVideo;
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
inputVideoFileLocation#3d0364ec id:long access_hash:long = InputFileLocation;
inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop;
inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
peerUser#9db1bc6d user_id:int = Peer;
peerChat#bad0e5bb chat_id:int = Peer;
storage.fileUnknown#aa963b05 = storage.FileType;
storage.fileJpeg#007efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#0a4f63c0 = storage.FileType;
storage.filePdf#ae1e508d = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
userEmpty#200250ba id:int = User;
userSelf#720535ec id:int first_name:string last_name:string phone:string photo:UserProfilePhoto status:UserStatus inactive:Bool = User;
userContact#f2fb8319 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
userRequest#22e8ceb0 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
userForeign#5214c89d id:int first_name:string last_name:string access_hash:long photo:UserProfilePhoto status:UserStatus = User;
userDeleted#b29ad7cc id:int first_name:string last_name:string = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
userStatusEmpty#09d05049 = UserStatus;
userStatusOnline#edb93949 expires:int = UserStatus;
userStatusOffline#008c703f was_online:int = UserStatus;
chatEmpty#9ba2d800 id:int = Chat;
chat#6e9c9bc7 id:int title:string photo:ChatPhoto participants_count:int date:int left:Bool version:int = Chat;
chatForbidden#fb0ccc41 id:int title:string date:int = Chat;
chatFull#630e61be id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantsForbidden#0fd2bb8a chat_id:int = ChatParticipants;
chatParticipants#7841b415 chat_id:int admin_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
message#22eb6aba id:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
messageForwarded#05f46804 id:int fwd_from_id:int fwd_date:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
messageService#9f8d60bb id:int from_id:int to_id:Peer out:Bool unread:Bool date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
messageMediaPhoto#c8c45a2a photo:Photo = MessageMedia;
messageMediaVideo#a2d24290 video:Video = MessageMedia;
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
messageMediaUnsupported#29632a36 bytes:bytes = MessageMedia;
messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
messageActionChatEditTitle#b5a1ce5a title:string = MessageAction;
messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction;
messageActionChatDeletePhoto#95e3fbef = MessageAction;
messageActionChatAddUser#5e3cfc4b user_id:int = MessageAction;
messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
dialog#ab3a99ac peer:Peer top_message:int unread_count:int notify_settings:PeerNotifySettings = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#22b56751 id:long access_hash:long user_id:int date:int caption:string geo:GeoPoint sizes:Vector<PhotoSize> = Photo;
photoSizeEmpty#0e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
videoEmpty#c10658a8 id:long = Video;
video#388fa391 id:long access_hash:long user_id:int date:int caption:string duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#2049d70c long:double lat:double = GeoPoint;
auth.checkedPhone#e300cc3b phone_registered:Bool phone_invited:Bool = auth.CheckedPhone;
auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
auth.authorization#f6b673a4 expires:int user:User = auth.Authorization;
auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization;
inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
inputNotifyUsers#193b4417 = InputNotifyPeer;
inputNotifyChats#4a95e84e = InputNotifyPeer;
inputNotifyAll#a429b886 = InputNotifyPeer;
inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents;
inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents;
inputPeerNotifySettings#46a2ce98 mute_until:int sound:string show_previews:Bool events_mask:int = InputPeerNotifySettings;
peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents;
peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents;
peerNotifySettingsEmpty#70a68512 = PeerNotifySettings;
peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool events_mask:int = PeerNotifySettings;
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
userFull#771095da user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool real_first_name:string real_last_name:string = UserFull;
contact#f911c994 user_id:int mutual:Bool = Contact;
importedContact#d0028438 user_id:int client_id:long = ImportedContact;
contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
contactFound#ea879f95 user_id:int = ContactFound;
contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
contactStatus#aa77b873 user_id:int expires:int = ContactStatus;
chatLocated#3631cf4c chat_id:int distance:int = ChatLocated;
contacts.foreignLinkUnknown#133421f8 = contacts.ForeignLink;
contacts.foreignLinkRequested#a7801f47 has_phone:Bool = contacts.ForeignLink;
contacts.foreignLinkMutual#1bea8ce1 = contacts.ForeignLink;
contacts.myLinkEmpty#d22a1c60 = contacts.MyLink;
contacts.myLinkRequested#6c69efee contact:Bool = contacts.MyLink;
contacts.myLinkContact#c240ebd9 = contacts.MyLink;
contacts.link#eccea3f5 my_link:contacts.MyLink foreign_link:contacts.ForeignLink user:User = contacts.Link;
contacts.contacts#6f8b8cb2 contacts:Vector<Contact> users:Vector<User> = contacts.Contacts;
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
contacts.importedContacts#ad524315 imported:Vector<ImportedContact> retry_contacts:Vector<long> users:Vector<User> = contacts.ImportedContacts;
contacts.blocked#1c138d15 blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
contacts.blockedSlice#900802a1 count:int blocked:Vector<ContactBlocked> users:Vector<User> = contacts.Blocked;
contacts.found#0566000e results:Vector<ContactFound> users:Vector<User> = contacts.Found;
contacts.suggested#5649dcc5 results:Vector<ContactSuggested> users:Vector<User> = contacts.Suggested;
messages.dialogs#15ba6c40 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#0b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messageEmpty#3f4e0648 = messages.Message;
messages.message#ff90c417 message:Message chats:Vector<Chat> users:Vector<User> = messages.Message;
messages.statedMessages#969478bb messages:Vector<Message> chats:Vector<Chat> users:Vector<User> pts:int seq:int = messages.StatedMessages;
messages.statedMessage#d07ae726 message:Message chats:Vector<Chat> users:Vector<User> pts:int seq:int = messages.StatedMessage;
messages.sentMessage#d1f4d35c id:int date:int pts:int seq:int = messages.SentMessage;
messages.chat#40e9002a chat:Chat users:Vector<User> = messages.Chat;
messages.chats#8150cbd8 chats:Vector<Chat> users:Vector<User> = messages.Chats;
messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;
messages.affectedHistory#b7de36f2 pts:int seq:int offset:int = messages.AffectedHistory;
inputMessagesFilterEmpty#57e2f66c = MessagesFilter;
inputMessagesFilterPhotos#9609a51c = MessagesFilter;
inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
updateNewMessage#013abdb3 message:Message pts:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
updateReadMessages#c6649e31 messages:Vector<int> pts:int = Update;
updateDeleteMessages#a92bfe26 messages:Vector<int> pts:int = Update;
updateRestoreMessages#d15de04d messages:Vector<int> pts:int = Update;
updateUserTyping#6baa8508 user_id:int = Update;
updateChatUserTyping#3c46cfe6 chat_id:int user_id:int = Update;
updateChatParticipants#07761198 participants:ChatParticipants = Update;
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
updateUserName#da22d9ad user_id:int first_name:string last_name:string = Update;
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
updateContactRegistered#2575bbb9 user_id:int date:int = Update;
updateContactLink#51a48a9a user_id:int my_link:contacts.MyLink foreign_link:contacts.ForeignLink = Update;
updateActivation#6f690963 user_id:int = Update;
updateNewAuthorization#8f06529a auth_key_id:long date:int device:string location:string = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
updates.difference#00f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
updatesTooLong#e317af7e = Updates;
updateShortMessage#d3f45784 id:int from_id:int message:string pts:int date:int seq:int = Updates;
updateShortChatMessage#2b2fbd4e id:int from_id:int chat_id:int message:string pts:int date:int seq:int = Updates;
updateShort#78d4dec1 update:Update date:int = Updates;
updatesCombined#725b04c3 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq_start:int seq:int = Updates;
updates#74ae4240 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq:int = Updates;
photos.photos#8dca6aa5 photos:Vector<Photo> users:Vector<User> = photos.Photos;
photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> = photos.Photos;
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
upload.file#096a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
dcOption#2ec2a43c id:int hostname:string ip_address:string port:int = DcOption;
config#2e54dd74 date:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int broadcast_size_max:int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
help.appUpdate#8987f311 id:int critical:Bool url:string text:string = help.AppUpdate;
help.noAppUpdate#c45a6536 = help.AppUpdate;
help.inviteText#18cb9f78 message:string = help.InviteText;
messages.statedMessagesLinks#3e74f5c6 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> links:Vector<contacts.Link> pts:int seq:int = messages.StatedMessages;
messages.statedMessageLink#a9af2881 message:Message chats:Vector<Chat> users:Vector<User> links:Vector<contacts.Link> pts:int seq:int = messages.StatedMessage;
messages.sentMessageLink#e9db4a3f id:int date:int pts:int seq:int links:Vector<contacts.Link> = messages.SentMessage;
inputGeoChat#74d456fa chat_id:int access_hash:long = InputGeoChat;
inputNotifyGeoChatPeer#4d8ddec8 peer:InputGeoChat = InputNotifyPeer;
geoChat#75eaea5a id:int access_hash:long title:string address:string venue:string geo:GeoPoint photo:ChatPhoto participants_count:int date:int checked_in:Bool version:int = Chat;
geoChatMessageEmpty#60311a9b chat_id:int id:int = GeoChatMessage;
geoChatMessage#4505f8e1 chat_id:int id:int from_id:int date:int message:string media:MessageMedia = GeoChatMessage;
geoChatMessageService#d34fa24e chat_id:int id:int from_id:int date:int action:MessageAction = GeoChatMessage;
geochats.statedMessage#17b1578b message:GeoChatMessage chats:Vector<Chat> users:Vector<User> seq:int = geochats.StatedMessage;
geochats.located#48feb267 results:Vector<ChatLocated> messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Located;
geochats.messages#d1526db1 messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Messages;
geochats.messagesSlice#bc5863e8 count:int messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Messages;
messageActionGeoChatCreate#6f038ebc title:string address:string = MessageAction;
messageActionGeoChatCheckin#0c7d53de = MessageAction;
updateNewGeoChatMessage#5a68e3f7 message:GeoChatMessage = Update;
wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
updateEncryptedMessagesRead#38fe25b7 chat_id:int max_date:int date:int = Update;
encryptedChatEmpty#ab7ec0a0 id:int = EncryptedChat;
encryptedChatWaiting#3bf703dc id:int access_hash:long date:int admin_id:int participant_id:int = EncryptedChat;
encryptedChatRequested#c878527e id:int access_hash:long date:int admin_id:int participant_id:int g_a:bytes = EncryptedChat;
encryptedChat#fa56ce36 id:int access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long = EncryptedChat;
encryptedChatDiscarded#13d6dd27 id:int = EncryptedChat;
inputEncryptedChat#f141b5e1 chat_id:int access_hash:long = InputEncryptedChat;
encryptedFileEmpty#c21f497e = EncryptedFile;
encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile;
inputEncryptedFileEmpty#1837c364 = InputEncryptedFile;
inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile;
inputEncryptedFile#5a17b5e5 id:long access_hash:long = InputEncryptedFile;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
encryptedMessage#ed18c118 random_id:long chat_id:int date:int bytes:bytes file:EncryptedFile = EncryptedMessage;
encryptedMessageService#23734b06 random_id:long chat_id:int date:int bytes:bytes = EncryptedMessage;
decryptedMessageLayer#99a438cf layer:int message:DecryptedMessage = DecryptedMessageLayer;
decryptedMessage#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
decryptedMessageService#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
decryptedMessageMediaEmpty#089f5c4a = DecryptedMessageMedia;
decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
messages.dhConfigNotModified#c0e24635 random:bytes = messages.DhConfig;
messages.dhConfig#2c221edd g:int p:bytes version:int random:bytes = messages.DhConfig;
messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
inputEncryptedFileBigUploaded#2dc173c8 id:long parts:int key_fingerprint:int = InputEncryptedFile;
updateChatParticipantAdd#3a0eeb22 chat_id:int user_id:int inviter_id:int version:int = Update;
updateChatParticipantDelete#6e5f8c22 chat_id:int user_id:int version:int = Update;
updateDcOptions#8e5e9873 dc_options:Vector<DcOption> = Update;
inputMediaUploadedAudio#4e498cab file:InputFile duration:int mime_type:string = InputMedia;
inputMediaAudio#89938781 id:InputAudio = InputMedia;
inputMediaUploadedDocument#34e794bd file:InputFile file_name:string mime_type:string = InputMedia;
inputMediaUploadedThumbDocument#3e46de5d file:InputFile thumb:InputFile file_name:string mime_type:string = InputMedia;
inputMediaDocument#d184e841 id:InputDocument = InputMedia;
messageMediaDocument#2fda2204 document:Document = MessageMedia;
messageMediaAudio#c6b68300 audio:Audio = MessageMedia;
inputAudioEmpty#d95adc84 = InputAudio;
inputAudio#77d440ff id:long access_hash:long = InputAudio;
inputDocumentEmpty#72f0eaae = InputDocument;
inputDocument#18798952 id:long access_hash:long = InputDocument;
inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
audioEmpty#586988d8 id:long = Audio;
audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio;
documentEmpty#36f8c871 id:long = Document;
document#9efc6326 id:long access_hash:long user_id:int date:int file_name:string mime_type:string size:int thumb:PhotoSize dc_id:int = Document;
help.support#17c6b5f6 phone_number:string user:User = help.Support;
decryptedMessageActionReadMessages#0c4f40be random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionDeleteMessages#65614304 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
notifyUsers#b4c83b4c = NotifyPeer;
notifyChats#c007cec3 = NotifyPeer;
notifyAll#74d07c60 = NotifyPeer;
updateUserBlocked#80ece81a user_id:int blocked:Bool = Update;
updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings = Update;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
auth.checkPhone#6fe51dfb phone_number:string = auth.CheckedPhone;
auth.sendCode#768d5f4d phone_number:string sms_type:int api_id:int api_hash:string lang_code:string = auth.SentCode;
auth.sendCall#03c51564 phone_number:string phone_code_hash:string = Bool;
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
auth.logOut#5717da40 = Bool;
auth.resetAuthorizations#9fab0d1a = Bool;
auth.sendInvites#771c1d97 phone_numbers:Vector<string> message:string = Bool;
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
account.registerDevice#446c712c token_type:int token:string device_model:string system_version:string app_version:string app_sandbox:Bool lang_code:string = Bool;
account.unregisterDevice#65c55b40 token_type:int token:string = Bool;
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
account.resetNotifySettings#db7e1747 = Bool;
account.updateProfile#f0888d68 first_name:string last_name:string = User;
account.updateStatus#6628562c offline:Bool = Bool;
account.getWallPapers#c04cfac2 = Vector<WallPaper>;
users.getUsers#0d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
contacts.getContacts#22c6aa08 hash:string = contacts.Contacts;
contacts.importContacts#da30b32d contacts:Vector<InputContact> replace:Bool = contacts.ImportedContacts;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.getSuggested#cd773428 limit:int = contacts.Suggested;
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
contacts.block#332b49fc id:InputUser = Bool;
contacts.unblock#e54100bd id:InputUser = Bool;
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
messages.getMessages#4222fa74 id:Vector<int> = messages.Messages;
messages.getDialogs#eccf1df6 offset:int max_id:int limit:int = messages.Dialogs;
messages.getHistory#92a1df2f peer:InputPeer offset:int max_id:int limit:int = messages.Messages;
messages.search#07e9f2ab peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages;
messages.readHistory#b04f2510 peer:InputPeer max_id:int offset:int = messages.AffectedHistory;
messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHistory;
messages.deleteMessages#14f2dd0a id:Vector<int> = Vector<int>;
messages.restoreMessages#395f9d7e id:Vector<int> = Vector<int>;
messages.receivedMessages#28abcb68 max_id:int = Vector<int>;
messages.setTyping#719839e9 peer:InputPeer typing:Bool = Bool;
messages.sendMessage#4cde0aab peer:InputPeer message:string random_id:long = messages.SentMessage;
messages.sendMedia#a3c85d76 peer:InputPeer media:InputMedia random_id:long = messages.StatedMessage;
messages.forwardMessages#514cd10f peer:InputPeer id:Vector<int> = messages.StatedMessages;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull;
messages.editChatTitle#b4bc68b5 chat_id:int title:string = messages.StatedMessage;
messages.editChatPhoto#d881821d chat_id:int photo:InputChatPhoto = messages.StatedMessage;
messages.addChatUser#2ee9ee9e chat_id:int user_id:InputUser fwd_limit:int = messages.StatedMessage;
messages.deleteChatUser#c3c5cd23 chat_id:int user_id:InputUser = messages.StatedMessage;
messages.createChat#419d9aee users:Vector<InputUser> title:string = messages.StatedMessage;
updates.getState#edd4882a = updates.State;
updates.getDifference#0a041495 pts:int date:int qts:int = updates.Difference;
photos.updateProfilePhoto#eef579a0 id:InputPhoto crop:InputPhotoCrop = UserProfilePhoto;
photos.uploadProfilePhoto#d50f9c88 file:InputFile caption:string geo_point:InputGeoPoint crop:InputPhotoCrop = photos.Photo;
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
help.getAppUpdate#c812ac7e device_model:string system_version:string app_version:string lang_code:string = help.AppUpdate;
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getInviteText#a4a95186 lang_code:string = help.InviteText;
photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos;
messages.forwardMessage#03f3f4f2 peer:InputPeer id:int random_id:long = messages.StatedMessage;
messages.sendBroadcast#41bb0972 contacts:Vector<InputUser> message:string media:InputMedia = messages.StatedMessages;
geochats.getLocated#7f192d8f geo_point:InputGeoPoint radius:int limit:int = geochats.Located;
geochats.getRecents#e1427e6f offset:int limit:int = geochats.Messages;
geochats.checkin#55b3e8fb peer:InputGeoChat = geochats.StatedMessage;
geochats.getFullChat#6722dd6f peer:InputGeoChat = messages.ChatFull;
geochats.editChatTitle#4c8e2273 peer:InputGeoChat title:string address:string = geochats.StatedMessage;
geochats.editChatPhoto#35d81a95 peer:InputGeoChat photo:InputChatPhoto = geochats.StatedMessage;
geochats.search#cfcdc44d peer:InputGeoChat q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = geochats.Messages;
geochats.getHistory#b53f7a68 peer:InputGeoChat offset:int max_id:int limit:int = geochats.Messages;
geochats.setTyping#08b8a729 peer:InputGeoChat typing:Bool = Bool;
geochats.sendMessage#061b0044 peer:InputGeoChat message:string random_id:long = geochats.StatedMessage;
geochats.sendMedia#b8f0deff peer:InputGeoChat media:InputMedia random_id:long = geochats.StatedMessage;
geochats.createGeoChat#0e092e16 title:string geo_point:InputGeoPoint address:string venue:string = geochats.StatedMessage;
messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig;
messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat;
messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat;
messages.discardEncryption#edd923c5 chat_id:int = Bool;
messages.setEncryptedTyping#791451ed peer:InputEncryptedChat typing:Bool = Bool;
messages.readEncryptedHistory#7f4b690a peer:InputEncryptedChat max_date:int = Bool;
messages.sendEncrypted#a9776773 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
messages.sendEncryptedFile#9a901b66 peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage;
messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
initConnection#69796de9 {X:Type} api_id:int device_model:string system_version:string app_version:string lang_code:string query:!X = X;
help.getSupport#9cdf08cd = help.Support;
invokeWithLayer15#b4418b64 {X:Type} query:!X = X;
/*
This file is part of VK/KittenPHP-DB-Engine.
VK/KittenPHP-DB-Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK/KittenPHP-DB-Engine. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include "tree.h"
#include "tl-parser.h"
#include "crc32.h"
#include "tl-tl.h"
#include "tools.h"
extern int verbosity;
extern int schema_version;
extern int output_expressions;
int total_types_num;
int total_constructors_num;
int total_functions_num;
/*char *tstrdup (const char *s) {
assert (s);
char *r = talloc (strlen (s) + 1);
memcpy (r, s, strlen (s) + 1);
return r;
}*/
char curch;
struct parse parse;
struct tree *tree;
struct tree *tree_alloc (void) {
struct tree *T = talloc (sizeof (*T));
assert (T);
memset (T, 0, sizeof (*T));
return T;
}
void tree_add_child (struct tree *P, struct tree *C) {
if (P->nc == P->size) {
void **t = talloc (sizeof (void *) * (++P->size));
memcpy (t, P->c, sizeof (void *) * (P->size - 1));
if (P->c) {
tfree (P->c, sizeof (void *) * (P->size - 1));
}
P->c = (void *)t;
assert (P->c);
}
P->c[P->nc ++] = C;
}
void tree_delete (struct tree *T) {
assert (T);
int i;
for (i = 0; i < T->nc; i++) {
assert (T->c[i]);
tree_delete (T->c[i]);
}
if (T->c) {
tfree (T->c, sizeof (void *) * T->nc);
}
tfree (T, sizeof (*T));
}
void tree_del_child (struct tree *P) {
assert (P->nc);
tree_delete (P->c[--P->nc]);
}
char nextch (void) {
if (parse.pos < parse.len - 1) {
curch = parse.text[++parse.pos];
} else {
curch = 0;
}
if (curch == 10) {
parse.line ++;
parse.line_pos = 0;
} else {
if (curch) {
parse.line_pos ++;
}
}
return curch;
}
struct parse save_parse (void) {
return parse;
}
void load_parse (struct parse _parse) {
parse = _parse;
curch = parse.pos > parse.len ? 0: parse.text[parse.pos] ;
}
int is_whitespace (char c) {
return (c <= 32);
}
int is_uletter (char c) {
return (c >= 'A' && c <= 'Z');
}
int is_lletter (char c) {
return (c >= 'a' && c <= 'z');
}
int is_letter (char c) {
return is_uletter (c) || is_lletter (c);
}
int is_digit (char c) {
return (c >= '0' && c <= '9');
}
int is_hexdigit (char c) {
return is_digit (c) || (c >= 'a' && c <= 'f');
}
int is_ident_char (char c) {
return is_digit (c) || is_letter (c) || c == '_';
}
int last_error_pos;
int last_error_line;
int last_error_line_pos;
char *last_error;
void parse_error (const char *e) {
if (parse.pos > last_error_pos) {
last_error_pos = parse.pos;
last_error_line = parse.line;
last_error_line_pos = parse.line_pos;
if (last_error) {
tfree (last_error, strlen (last_error) + 1);
}
last_error = tstrdup (e);
}
}
void tl_print_parse_error (void) {
fprintf (stderr, "Error near line %d pos %d: `%s`\n", last_error_line + 1, last_error_line_pos + 1, last_error);
}
char *parse_lex (void) {
while (1) {
while (curch && is_whitespace (curch)) { nextch (); }
if (curch == '/' && nextch () == '/') {
while (nextch () != 10);
nextch ();
} else {
break;
}
}
if (!curch) {
parse.lex.len = 0;
parse.lex.type = lex_eof;
return (parse.lex.ptr = 0);
}
char *p = parse.text + parse.pos;
parse.lex.flags = 0;
switch (curch) {
case '-':
if (nextch () != '-' || nextch () != '-') {
parse_error ("Can not parse triple minus");
parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1);
} else {
parse.lex.len = 3;
parse.lex.type = lex_triple_minus;
nextch ();
return (parse.lex.ptr = p);
}
case ':':
case ';':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '=':
case '#':
case '?':
case '%':
case '<':
case '>':
case '+':
case ',':
case '*':
case '_':
case '!':
case '.':
nextch ();
parse.lex.len = 1;
parse.lex.type = lex_char;
return (parse.lex.ptr = p);
case 'a'...'z':
case 'A'...'Z':
parse.lex.flags = 0;
if (is_uletter (curch)) {
while (is_ident_char (nextch ()));
parse.lex.len = parse.text + parse.pos - p;
parse.lex.ptr = p;
if (parse.lex.len == 5 && !memcmp (parse.lex.ptr, "Final", 5)) {
parse.lex.type = lex_final;
} else if (parse.lex.len == 3 && !memcmp (parse.lex.ptr, "New", 3)) {
parse.lex.type = lex_new;
} else if (parse.lex.len == 5 && !memcmp (parse.lex.ptr, "Empty", 5)) {
parse.lex.type = lex_empty;
} else {
parse.lex.type = lex_uc_ident;
}
return (parse.lex.ptr = p);
}
while (is_ident_char (nextch ()));
if (curch == '.' && !is_letter (parse.text[parse.pos + 1])) {
parse.lex.len = parse.text + parse.pos - p;
parse.lex.type = lex_lc_ident;
return (parse.lex.ptr = p);
}
if (curch == '.') {
parse.lex.flags |= 1;
nextch ();
if (is_uletter (curch)) {
while (is_ident_char (nextch ()));
parse.lex.len = parse.text + parse.pos - p;
parse.lex.type = lex_uc_ident;
return (parse.lex.ptr = p);
}
if (is_lletter (curch)) {
while (is_ident_char (nextch ()));
} else {
parse_error ("Expected letter");
parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1);
}
}
if (curch == '#') {
parse.lex.flags |= 2;
int i;
for (i = 0; i < 8; i++) {
if (!is_hexdigit (nextch())) {
parse_error ("Hex digit expected");
parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1);
}
}
nextch ();
}
parse.lex.len = parse.text + parse.pos - p;
parse.lex.type = lex_lc_ident;
return (parse.lex.ptr = p);
case '0'...'9':
while (is_digit (nextch ()));
parse.lex.len = parse.text + parse.pos - p;
parse.lex.type = lex_num;
return (parse.lex.ptr = p);
default:
parse_error ("Unknown lexem");
parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1);
}
}
int expect (char *s) {
if (!parse.lex.ptr || parse.lex.ptr == (void *)-1 || parse.lex.type == lex_error || parse.lex.type == lex_none || parse.lex.len != (int)strlen (s) || memcmp (s, parse.lex.ptr, parse.lex.len)) {
static char buf[1000];
sprintf (buf, "Expected %s", s);
parse_error (buf);
return -1;
} else {
parse_lex ();
}
return 1;
}
struct parse *tl_init_parse_file (const char *fname) {
int fd = open (fname, O_RDONLY);
if (fd < 0) {
fprintf (stderr, "Error %m\n");
assert (0);
return 0;
}
long long size = lseek (fd, 0, SEEK_END);
if (size <= 0) {
fprintf (stderr, "size is %lld. Too small.\n", size);
return 0;
}
static struct parse save;
save.text = talloc (size);
lseek (fd, 0, SEEK_SET);
save.len = read (fd, save.text, size);
assert (save.len == size);
save.pos = 0;
save.line = 0;
save.line_pos = 0;
save.lex.ptr = save.text;
save.lex.len = 0;
save.lex.type = lex_none;
return &save;
}
#define PARSE_INIT(_type) struct parse save = save_parse (); struct tree *T = tree_alloc (); T->type = (_type); T->lex_line = parse.line; T->lex_line_pos = parse.line_pos; struct tree *S __attribute__ ((unused));
#define PARSE_FAIL load_parse (save); tree_delete (T); return 0;
#define PARSE_OK return T;
#define PARSE_TRY_PES(x) if (!(S = x ())) { PARSE_FAIL; } { tree_add_child (T, S); }
#define PARSE_TRY_OPT(x) if ((S = x ())) { tree_add_child (T, S); PARSE_OK }
#define PARSE_TRY(x) S = x ();
#define PARSE_ADD(_type) S = tree_alloc (); S->type = _type; tree_add_child (T, S);
#define EXPECT(s) if (expect (s) < 0) { PARSE_FAIL; }
#define LEX_CHAR(c) (parse.lex.type == lex_char && *parse.lex.ptr == c)
struct tree *parse_args (void);
struct tree *parse_expr (void);
struct tree *parse_boxed_type_ident (void) {
PARSE_INIT (type_boxed_type_ident);
if (parse.lex.type != lex_uc_ident) {
parse_error ("Can not parse boxed type");
PARSE_FAIL;
} else {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
}
}
struct tree *parse_full_combinator_id (void) {
PARSE_INIT (type_full_combinator_id);
if (parse.lex.type == lex_lc_ident || LEX_CHAR('_')) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse full combinator id");
PARSE_FAIL;
}
}
struct tree *parse_combinator_id (void) {
PARSE_INIT (type_combinator_id);
if (parse.lex.type == lex_lc_ident && !(parse.lex.flags & 2)) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse combinator id");
PARSE_FAIL;
}
}
struct tree *parse_var_ident (void) {
PARSE_INIT (type_var_ident);
if ((parse.lex.type == lex_lc_ident || parse.lex.type == lex_uc_ident) && !(parse.lex.flags & 3)) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse var ident");
PARSE_FAIL;
}
}
struct tree *parse_var_ident_opt (void) {
PARSE_INIT (type_var_ident_opt);
if ((parse.lex.type == lex_lc_ident || parse.lex.type == lex_uc_ident)&& !(parse.lex.flags & 3)) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else if (LEX_CHAR ('_')) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse var ident opt");
PARSE_FAIL;
}
}
struct tree *parse_nat_const (void) {
PARSE_INIT (type_nat_const);
if (parse.lex.type == lex_num) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse nat const");
PARSE_FAIL;
}
}
struct tree *parse_type_ident (void) {
PARSE_INIT (type_type_ident);
if (parse.lex.type == lex_uc_ident && !(parse.lex.flags & 2)) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else if (parse.lex.type == lex_lc_ident && !(parse.lex.flags & 2)) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else if (LEX_CHAR ('#')) {
T->text = parse.lex.ptr;
T->len = parse.lex.len;
T->flags = parse.lex.flags;
parse_lex ();
PARSE_OK;
} else {
parse_error ("Can not parse type ident");
PARSE_FAIL;
}
}
struct tree *parse_term (void) {
PARSE_INIT (type_term);
while (LEX_CHAR ('%')) {
EXPECT ("%")
PARSE_ADD (type_percent);
}
if (LEX_CHAR ('(')) {
EXPECT ("(");
PARSE_TRY_PES (parse_expr);
EXPECT (")");
PARSE_OK;
}
PARSE_TRY (parse_type_ident);
if (S) {
tree_add_child (T, S);
if (LEX_CHAR ('<')) {
EXPECT ("<");
while (1) {
PARSE_TRY_PES (parse_expr);
if (LEX_CHAR ('>')) { break; }
EXPECT (",");
}
EXPECT (">");
}
PARSE_OK;
}
PARSE_TRY_OPT (parse_type_ident);
PARSE_TRY_OPT (parse_var_ident);
PARSE_TRY_OPT (parse_nat_const);
PARSE_FAIL;
}
struct tree *parse_nat_term (void) {
PARSE_INIT (type_nat_term);
PARSE_TRY_PES (parse_term);
PARSE_OK;
}
struct tree *parse_subexpr (void) {
PARSE_INIT (type_subexpr);
int was_term = 0;
int cc = 0;
while (1) {
PARSE_TRY (parse_nat_const);
if (S) {
tree_add_child (T, S);
} else if (!was_term) {
was_term = 1;
PARSE_TRY (parse_term);
if (S) {
tree_add_child (T, S);
} else {
break;
}
}
cc ++;
if (!LEX_CHAR ('+')) {
break;
}
EXPECT ("+");
}
if (!cc) {
PARSE_FAIL;
} else {
PARSE_OK;
}
}
struct tree *parse_expr (void) {
PARSE_INIT (type_expr);
int cc = 0;
while (1) {
PARSE_TRY (parse_subexpr);
if (S) {
tree_add_child (T, S);
cc ++;
} else {
if (cc < 1) { PARSE_FAIL; }
else { PARSE_OK; }
}
}
}
struct tree *parse_final_empty (void) {
PARSE_INIT (type_final_empty);
EXPECT ("Empty");
PARSE_TRY_PES (parse_boxed_type_ident);
PARSE_OK;
}
struct tree *parse_final_new (void) {
PARSE_INIT (type_final_new);
EXPECT ("New");
PARSE_TRY_PES (parse_boxed_type_ident);
PARSE_OK;
}
struct tree *parse_final_final (void) {
PARSE_INIT (type_final_final);
EXPECT ("Final");
PARSE_TRY_PES (parse_boxed_type_ident);
PARSE_OK;
}
struct tree *parse_partial_comb_app_decl (void) {
PARSE_INIT (type_partial_comb_app_decl);
PARSE_TRY_PES (parse_combinator_id);
while (1) {
PARSE_TRY_PES (parse_subexpr);
if (LEX_CHAR (';')) { break; }
}
PARSE_OK;
}
struct tree *parse_partial_type_app_decl (void) {
PARSE_INIT (type_partial_type_app_decl);
PARSE_TRY_PES (parse_boxed_type_ident);
if (LEX_CHAR ('<')) {
EXPECT ("<");
while (1) {
PARSE_TRY_PES (parse_expr);
if (LEX_CHAR ('>')) { break; }
EXPECT (",");
}
EXPECT (">");
PARSE_OK;
} else {
while (1) {
PARSE_TRY_PES (parse_subexpr);
if (LEX_CHAR (';')) { break; }
}
PARSE_OK;
}
}
struct tree *parse_multiplicity (void) {
PARSE_INIT (type_multiplicity);
PARSE_TRY_PES (parse_nat_term);
PARSE_OK;
}
struct tree *parse_type_term (void) {
PARSE_INIT (type_type_term);
PARSE_TRY_PES (parse_term);
PARSE_OK;
}
struct tree *parse_optional_arg_def (void) {
PARSE_INIT (type_optional_arg_def);
PARSE_TRY_PES (parse_var_ident);
EXPECT (".");
PARSE_TRY_PES (parse_nat_const);
EXPECT ("?");
PARSE_OK;
}
struct tree *parse_args4 (void) {
PARSE_INIT (type_args4);
struct parse so = save_parse ();
PARSE_TRY (parse_optional_arg_def);
if (S) {
tree_add_child (T, S);
} else {
load_parse (so);
}
if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam);
EXPECT ("!");
}
PARSE_TRY_PES (parse_type_term);
PARSE_OK;
}
struct tree *parse_args3 (void) {
PARSE_INIT (type_args3);
PARSE_TRY_PES (parse_var_ident_opt);
EXPECT (":");
struct parse so = save_parse ();
PARSE_TRY (parse_optional_arg_def);
if (S) {
tree_add_child (T, S);
} else {
load_parse (so);
}
if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam);
EXPECT ("!");
}
PARSE_TRY_PES (parse_type_term);
PARSE_OK;
}
struct tree *parse_args2 (void) {
PARSE_INIT (type_args2);
PARSE_TRY (parse_var_ident_opt);
if (S && LEX_CHAR (':')) {
tree_add_child (T, S);
EXPECT (":");
} else {
load_parse (save);
}
struct parse so = save_parse ();
PARSE_TRY (parse_optional_arg_def);
if (S) {
tree_add_child (T, S);
} else {
load_parse (so);
}
struct parse save2 = save_parse ();
PARSE_TRY (parse_multiplicity);
if (S && LEX_CHAR ('*')) {
tree_add_child (T, S);
EXPECT ("*");
} else {
load_parse (save2);
}
EXPECT ("[");
while (1) {
if (LEX_CHAR (']')) { break; }
PARSE_TRY_PES (parse_args);
}
EXPECT ("]");
PARSE_OK;
}
struct tree *parse_args1 (void) {
PARSE_INIT (type_args1);
EXPECT ("(");
while (1) {
PARSE_TRY_PES (parse_var_ident_opt);
if (LEX_CHAR(':')) { break; }
}
EXPECT (":");
struct parse so = save_parse ();
PARSE_TRY (parse_optional_arg_def);
if (S) {
tree_add_child (T, S);
} else {
load_parse (so);
}
if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam);
EXPECT ("!");
}
PARSE_TRY_PES (parse_type_term);
EXPECT (")");
PARSE_OK;
}
struct tree *parse_args (void) {
PARSE_INIT (type_args);
PARSE_TRY_OPT (parse_args1);
PARSE_TRY_OPT (parse_args2);
PARSE_TRY_OPT (parse_args3);
PARSE_TRY_OPT (parse_args4);
PARSE_FAIL;
}
struct tree *parse_opt_args (void) {
PARSE_INIT (type_opt_args);
while (1) {
PARSE_TRY_PES (parse_var_ident);
if (parse.lex.type == lex_char && *parse.lex.ptr == ':') { break;}
}
EXPECT (":");
PARSE_TRY_PES (parse_type_term);
PARSE_OK;
}
struct tree *parse_final_decl (void) {
PARSE_INIT (type_final_decl);
PARSE_TRY_OPT (parse_final_new);
PARSE_TRY_OPT (parse_final_final);
PARSE_TRY_OPT (parse_final_empty);
PARSE_FAIL;
}
struct tree *parse_partial_app_decl (void) {
PARSE_INIT (type_partial_app_decl);
PARSE_TRY_OPT (parse_partial_type_app_decl);
PARSE_TRY_OPT (parse_partial_comb_app_decl);
PARSE_FAIL;
}
struct tree *parse_result_type (void) {
PARSE_INIT (type_result_type);
PARSE_TRY_PES (parse_boxed_type_ident);
if (LEX_CHAR ('<')) {
EXPECT ("<");
while (1) {
PARSE_TRY_PES (parse_expr);
if (LEX_CHAR ('>')) { break; }
EXPECT (",");
}
EXPECT (">");
PARSE_OK;
} else {
while (1) {
if (LEX_CHAR (';')) { PARSE_OK; }
PARSE_TRY_PES (parse_subexpr);
}
}
}
struct tree *parse_combinator_decl (void) {
PARSE_INIT (type_combinator_decl);
PARSE_TRY_PES (parse_full_combinator_id)
while (1) {
if (LEX_CHAR ('{')) {
parse_lex ();
PARSE_TRY_PES (parse_opt_args);
EXPECT ("}");
} else {
break;
}
}
while (1) {
if (LEX_CHAR ('=')) { break; }
PARSE_TRY_PES (parse_args);
}
EXPECT ("=");
PARSE_ADD (type_equals);
PARSE_TRY_PES (parse_result_type);
PARSE_OK;
}
struct tree *parse_builtin_combinator_decl (void) {
PARSE_INIT (type_builtin_combinator_decl);
PARSE_TRY_PES (parse_full_combinator_id)
EXPECT ("?");
EXPECT ("=");
PARSE_TRY_PES (parse_boxed_type_ident);
PARSE_OK;
}
struct tree *parse_declaration (void) {
PARSE_INIT (type_declaration);
PARSE_TRY_OPT (parse_combinator_decl);
PARSE_TRY_OPT (parse_partial_app_decl);
PARSE_TRY_OPT (parse_final_decl);
PARSE_TRY_OPT (parse_builtin_combinator_decl);
PARSE_FAIL;
}
struct tree *parse_constr_declarations (void) {
PARSE_INIT (type_constr_declarations);
if (parse.lex.type == lex_triple_minus || parse.lex.type == lex_eof) { PARSE_OK; }
while (1) {
PARSE_TRY_PES (parse_declaration);
EXPECT (";");
if (parse.lex.type == lex_eof || parse.lex.type == lex_triple_minus) { PARSE_OK; }
}
}
struct tree *parse_fun_declarations (void) {
PARSE_INIT (type_fun_declarations);
if (parse.lex.type == lex_triple_minus || parse.lex.type == lex_eof) { PARSE_OK; }
while (1) {
PARSE_TRY_PES (parse_declaration);
EXPECT (";");
if (parse.lex.type == lex_eof || parse.lex.type == lex_triple_minus) { PARSE_OK; }
}
}
struct tree *parse_program (void) {
PARSE_INIT (type_tl_program);
while (1) {
PARSE_TRY_PES (parse_constr_declarations);
if (parse.lex.type == lex_eof) { PARSE_OK; }
if (parse.lex.type == lex_error || expect ("---") < 0 || expect ("functions") < 0 || expect ("---") < 0) { PARSE_FAIL; }
PARSE_TRY_PES (parse_fun_declarations);
if (parse.lex.type == lex_eof) { PARSE_OK; }
if (parse.lex.type == lex_error || expect ("---") < 0 || expect ("types") < 0 || expect ("---") < 0) { PARSE_FAIL; }
}
}
struct tree *tl_parse_lex (struct parse *_parse) {
assert (_parse);
load_parse (*_parse);
if (parse.lex.type == lex_none) {
parse_lex ();
}
if (parse.lex.type == lex_error) {
return 0;
}
return parse_program ();
}
int mystrcmp2 (const char *b, int len, const char *a) {
int c = strncmp (b, a, len);
return c ? a[len] ? -1 : 0 : c;
}
char *mystrdup (const char *a, int len) {
char *z = talloc (len + 1);
memcpy (z, a, len);
z[len] = 0;
return z;
}
struct tl_program *tl_program_cur;
#define TL_TRY_PES(x) if (!(x)) { return 0; }
#define tl_type_cmp(a,b) (strcmp (a->id, b->id))
DEFINE_TREE (tl_type,struct tl_type *,tl_type_cmp,0)
struct tree_tl_type *tl_type_tree;
DEFINE_TREE (tl_constructor,struct tl_constructor *,tl_type_cmp,0)
struct tree_tl_constructor *tl_constructor_tree;
struct tree_tl_constructor *tl_function_tree;
DEFINE_TREE (tl_var,struct tl_var *,tl_type_cmp,0)
struct tl_var_value {
struct tl_combinator_tree *ptr;
struct tl_combinator_tree *val;
int num_val;
};
#define tl_var_value_cmp(a,b) (((char *)a.ptr) - ((char *)b.ptr))
struct tl_var_value empty;
DEFINE_TREE (var_value, struct tl_var_value, tl_var_value_cmp, empty)
//tree_tl_var_t *tl_var_tree;
DEFINE_TREE (tl_field,char *,strcmp, 0)
//tree_tl_field_t *tl_field_tree;
#define TL_FAIL return 0;
#define TL_INIT(x) struct tl_combinator_tree *x = 0;
#define TL_TRY(f,x) { struct tl_combinator_tree *_t = f; if (!_t) { TL_FAIL;} x = tl_union (x, _t); if (!x) { TL_FAIL; }}
#define TL_ERROR(...) fprintf (stderr, __VA_ARGS__);
#define TL_WARNING(...) fprintf (stderr, __VA_ARGS__);
void tl_set_var_value (struct tree_var_value **T, struct tl_combinator_tree *var, struct tl_combinator_tree *value) {
struct tl_var_value t = {.ptr = var, .val = value, .num_val = 0};
if (tree_lookup_var_value (*T, t).ptr) {
*T = tree_delete_var_value (*T, t);
}
*T = tree_insert_var_value (*T, t, lrand48 ());
}
void tl_set_var_value_num (struct tree_var_value **T, struct tl_combinator_tree *var, struct tl_combinator_tree *value, long long num_value) {
struct tl_var_value t = {.ptr = var, .val = value, .num_val = num_value};
if (tree_lookup_var_value (*T, t).ptr) {
*T = tree_delete_var_value (*T, t);
}
*T = tree_insert_var_value (*T, t, lrand48 ());
}
struct tl_combinator_tree *tl_get_var_value (struct tree_var_value **T, struct tl_combinator_tree *var) {
struct tl_var_value t = {.ptr = var, .val = 0, .num_val = 0};
struct tl_var_value r = tree_lookup_var_value (*T, t);
return r.ptr ? r.val : 0;
}
int tl_get_var_value_num (struct tree_var_value **T, struct tl_combinator_tree *var) {
struct tl_var_value t = {.ptr = var, .val = 0};
struct tl_var_value r = tree_lookup_var_value (*T, t);
return r.ptr ? r.num_val : 0;
}
int namespace_level;
struct tree_tl_var *vars[10];
struct tree_tl_field *fields[10];
struct tl_var *last_num_var[10];
int tl_is_type_name (const char *id, int len) {
if (len == 1 && *id == '#') { return 1;}
int ok = id[0] >= 'A' && id[0] <= 'Z';
int i;
for (i = 0; i < len - 1; i++) if (id[i] == '.') {
ok = id[i + 1] >= 'A' && id[i + 1] <= 'Z';
}
return ok;
}
int tl_add_field (char *id) {
assert (namespace_level < 10);
assert (namespace_level >= 0);
if (tree_lookup_tl_field (fields[namespace_level], id)) {
return 0;
}
fields[namespace_level] = tree_insert_tl_field (fields[namespace_level], id, lrand48 ());
return 1;
}
void tl_clear_fields (void) {
// tree_act_tl_field (fields[namespace_level], (void *)free);
fields[namespace_level] = tree_clear_tl_field (fields[namespace_level]);
}
struct tl_var *tl_add_var (char *id, struct tl_combinator_tree *ptr, int type) {
struct tl_var *v = talloc (sizeof (*v));
v->id = tstrdup (id);
v->type = type;
v->ptr = ptr;
v->flags = 0;
if (tree_lookup_tl_var (vars[namespace_level], v)) {
return 0;
}
vars[namespace_level] = tree_insert_tl_var (vars[namespace_level], v, lrand48 ());
if (type) {
last_num_var[namespace_level] = v;
}
return v;
}
void tl_del_var (struct tl_var *v) {
// free (v->id);
tfree (v, sizeof (*v));
}
void tl_clear_vars (void) {
tree_act_tl_var (vars[namespace_level], tl_del_var);
vars[namespace_level] = tree_clear_tl_var (vars[namespace_level]);
last_num_var[namespace_level] = 0;
}
struct tl_var *tl_get_last_num_var (void) {
return last_num_var[namespace_level];
}
struct tl_var *tl_get_var (char *_id, int len) {
char *id = mystrdup (_id, len);
struct tl_var v = {.id = id};
int i;
for (i = namespace_level; i >= 0; i--) {
struct tl_var *w = tree_lookup_tl_var (vars[i], &v);
if (w) {
tfree (id, len + 1);
return w;
}
}
return 0;
}
void namespace_push (void) {
namespace_level ++;
assert (namespace_level < 10);
tl_clear_vars ();
tl_clear_fields ();
}
void namespace_pop (void) {
namespace_level --;
assert (namespace_level >= 0);
}
struct tl_type *tl_get_type (const char *_id, int len) {
char *id = mystrdup (_id, len);
struct tl_type _t = {.id = id};
struct tl_type *r = tree_lookup_tl_type (tl_type_tree, &_t);
tfree (id, len + 1);
return r;
}
struct tl_type *tl_add_type (const char *_id, int len, int params_num, long long params_types) {
char *id = talloc (len + 1);
memcpy (id, _id, len);
id[len] = 0;
struct tl_type _t = {.id = id};
struct tl_type *_r = 0;
if ((_r = tree_lookup_tl_type (tl_type_tree, &_t))) {
tfree (id, len + 1);
if (params_num >= 0 && (_r->params_num != params_num || _r->params_types != params_types)) {
TL_ERROR ("Wrong params_num or types for type %s\n", _r->id);
return 0;
}
return _r;
}
struct tl_type *t = talloc (sizeof (*t));
t->id = id;
t->print_id = tstrdup (t->id);
int i;
for (i = 0; i < len; i++) if (t->print_id[i] == '.' || t->print_id[i] == '#' || t->print_id[i] == ' ') {
t->print_id[i] = '$';
}
t->name = 0;
t->constructors_num = 0;
t->constructors = 0;
t->flags = 0;
t->real_id = 0;
if (params_num >= 0) {
assert (params_num <= 64);
t->params_num = params_num;
t->params_types = params_types;
} else {
t->flags |= 4;
t->params_num = -1;
}
tl_type_tree = tree_insert_tl_type (tl_type_tree, t, lrand48 ());
total_types_num ++;
return t;
}
void tl_add_type_param (struct tl_type *t, int x) {
assert (t->flags & 4);
assert (t->params_num <= 64);
if (x) {
t->params_types |= (1ull << (t->params_num ++));
} else {
t->params_num ++;
}
}
int tl_type_set_params (struct tl_type *t, int x, long long y) {
if (t->flags & 4) {
t->params_num = x;
t->params_types = y;
t->flags &= ~4;
} else {
if (t->params_num != x || t->params_types != y) {
fprintf (stderr, "Wrong num of params (type %s)\n", t->id);
return 0;
}
}
return 1;
}
void tl_type_finalize (struct tl_type *t) {
t->flags &= ~4;
}
struct tl_constructor *tl_get_constructor (const char *_id, int len) {
char *id = mystrdup (_id, len);
struct tl_constructor _t = {.id = id};
struct tl_constructor *r = tree_lookup_tl_constructor (tl_constructor_tree, &_t);
tfree (id, len + 1);
return r;
}
struct tl_constructor *tl_add_constructor (struct tl_type *a, const char *_id, int len, int force_magic) {
assert (a);
if (a->flags & 1) {
TL_ERROR ("New constructor for type `%s` after final statement\n", a->id);
return 0;
}
int x = 0;
while (x < len && (_id[x] != '#' || force_magic)) { x++; }
char *id = talloc (x + 1);
memcpy (id, _id, x);
id[x] = 0;
unsigned magic = 0;
if (x < len) {
assert (len - x == 9);
int i;
for (i = 1; i <= 8; i++) {
magic = (magic << 4) + (_id[x + i] <= '9' ? _id[x + i] - '0' : _id[x + i] - 'a' + 10);
}
assert (magic && magic != (unsigned)-1);
}
if (*id != '_') {
struct tl_constructor _t = {.id = id};
if (tree_lookup_tl_constructor (tl_constructor_tree, &_t)) {
TL_ERROR ("Duplicate constructor id `%s`\n", id);
tfree (id, len + 1);
return 0;
}
} else {
assert (len == 1);
}
struct tl_constructor *t = talloc (sizeof (*t));
t->type = a;
t->name = magic;
t->id = id;
t->print_id = tstrdup (id);
t->real_id = 0;
int i;
for (i = 0; i < len; i++) if (t->print_id[i] == '.' || t->print_id[i] == '#' || t->print_id[i] == ' ') {
t->print_id[i] = '$';
}
t->left = t->right = 0;
a->constructors = realloc (a->constructors, sizeof (void *) * (a->constructors_num + 1));
assert (a->constructors);
a->constructors[a->constructors_num ++] = t;
if (*id != '_') {
tl_constructor_tree = tree_insert_tl_constructor (tl_constructor_tree, t, lrand48 ());
}
total_constructors_num ++;
a->flags |= FLAG_DEFAULT_CONSTRUCTOR;
return t;
}
struct tl_constructor *tl_get_function (const char *_id, int len) {
char *id = mystrdup (_id, len);
struct tl_constructor _t = {.id = id};
struct tl_constructor *r = tree_lookup_tl_constructor (tl_function_tree, &_t);
tfree (id, len + 1);
return r;
}
struct tl_constructor *tl_add_function (struct tl_type *a, const char *_id, int len, int force_magic) {
// assert (a);
int x = 0;
while (x < len && ((_id[x] != '#') || force_magic)) { x++; }
char *id = talloc (x + 1);
memcpy (id, _id, x);
id[x] = 0;
unsigned magic = 0;
if (x < len) {
assert (len - x == 9);
int i;
for (i = 1; i <= 8; i++) {
magic = (magic << 4) + (_id[x + i] <= '9' ? _id[x + i] - '0' : _id[x + i] - 'a' + 10);
}
assert (magic && magic != (unsigned)-1);
}
struct tl_constructor _t = {.id = id};
if (tree_lookup_tl_constructor (tl_function_tree, &_t)) {
TL_ERROR ("Duplicate function id `%s`\n", id);
tfree (id, len + 1);
return 0;
}
struct tl_constructor *t = talloc (sizeof (*t));
t->type = a;
t->name = magic;
t->id = id;
t->print_id = tstrdup (id);
t->real_id = 0;
int i;
for (i = 0; i < len; i++) if (t->print_id[i] == '.' || t->print_id[i] == '#' || t->print_id[i] == ' ') {
t->print_id[i] = '$';
}
t->left = t->right = 0;
tl_function_tree = tree_insert_tl_constructor (tl_function_tree, t, lrand48 ());
total_functions_num ++;
return t;
}
static char buf[(1 << 20)];
int buf_pos;
struct tl_combinator_tree *alloc_ctree_node (void) {
struct tl_combinator_tree *T = talloc (sizeof (*T));
assert (T);
memset (T, 0, sizeof (*T));
return T;
}
struct tl_combinator_tree *tl_tree_dup (struct tl_combinator_tree *T) {
if (!T) { return 0; }
struct tl_combinator_tree *S = talloc (sizeof (*S));
memcpy (S, T, sizeof (*S));
S->left = tl_tree_dup (T->left);
S->right = tl_tree_dup (T->right);
return S;
}
struct tl_type *tl_tree_get_type (struct tl_combinator_tree *T) {
assert (T->type == type_type);
if (T->act == act_array) { return 0;}
while (T->left) {
T = T->left;
if (T->act == act_array) { return 0;}
assert (T->type == type_type);
}
assert (T->act == act_type || T->act == act_var || T->act == act_array);
return T->act == act_type ? T->data : 0;
}
void tl_tree_set_len (struct tl_combinator_tree *T) {
TL_INIT (H);
H = T;
while (H->left) {
H->left->type_len = H->type_len + 1;
H = H->left;
}
assert (H->type == type_type);
struct tl_type *t = H->data;
assert (t);
assert (H->type_len == t->params_num);
}
void tl_buf_reset (void) {
buf_pos = 0;
}
void tl_buf_add_string (char *s, int len) {
if (len < 0) { len = strlen (s); }
buf[buf_pos ++] = ' ';
memcpy (buf + buf_pos, s, len); buf_pos += len;
buf[buf_pos] = 0;
}
void tl_buf_add_string_nospace (char *s, int len) {
if (len < 0) { len = strlen (s); }
// if (buf_pos) { buf[buf_pos ++] = ' '; }
memcpy (buf + buf_pos, s, len); buf_pos += len;
buf[buf_pos] = 0;
}
void tl_buf_add_string_q (char *s, int len, int x) {
if (x) {
tl_buf_add_string (s, len);
} else {
tl_buf_add_string_nospace (s, len);
}
}
void tl_buf_add_tree (struct tl_combinator_tree *T, int x) {
if (!T) { return; }
assert (T != (void *)-1l && T != (void *)-2l);
switch (T->act) {
case act_question_mark:
tl_buf_add_string_q ("?", -1, x);
return;
case act_type:
if ((T->flags & 1) && !(T->flags & 4)) {
tl_buf_add_string_q ("%", -1, x);
x = 0;
}
if (T->flags & 2) {
tl_buf_add_string_q ((char *)T->data, -1, x);
} else {
struct tl_type *t = T->data;
if (T->flags & 4) {
assert (t->constructors_num == 1);
tl_buf_add_string_q (t->constructors[0]->real_id ? t->constructors[0]->real_id : t->constructors[0]->id, -1, x);
} else {
tl_buf_add_string_q (t->real_id ? t->real_id : t->id, -1, x);
}
}
return;
case act_field:
if (T->data) {
tl_buf_add_string_q ((char *)T->data, -1, x);
x = 0;
tl_buf_add_string_q (":", -1, 0);
}
tl_buf_add_tree (T->left, x);
tl_buf_add_tree (T->right, 1);
return;
case act_union:
tl_buf_add_tree (T->left, x);
tl_buf_add_tree (T->right, 1);
return;
case act_var:
{
if (T->data == (void *)-1l) { return; }
struct tl_combinator_tree *v = T->data;
tl_buf_add_string_q ((char *)v->data, -1, x);
if (T->type == type_num && T->type_flags) {
static char _buf[30];
sprintf (_buf, "+%lld", T->type_flags);
tl_buf_add_string_q (_buf, -1, 0);
}
}
return;
case act_arg:
tl_buf_add_tree (T->left, x);
tl_buf_add_tree (T->right, 1);
return;
case act_array:
if (T->left && !(T->left->flags & 128)) {
tl_buf_add_tree (T->left, x);
x = 0;
tl_buf_add_string_q ("*", -1, x);
}
tl_buf_add_string_q ("[", -1, x);
tl_buf_add_tree (T->right, 1);
tl_buf_add_string_q ("]", -1, 1);
return;
case act_plus:
tl_buf_add_tree (T->left, x);
tl_buf_add_string_q ("+", -1, 0);
tl_buf_add_tree (T->right, 0);
return;
case act_nat_const:
{
static char _buf[30];
snprintf (_buf, 29, "%lld", T->type_flags);
tl_buf_add_string_q (_buf, -1, x);
return;
}
case act_opt_field:
{
struct tl_combinator_tree *v = T->left->data;
tl_buf_add_string_q ((char *)v->data, -1, x);
tl_buf_add_string_q (".", -1, 0);
static char _buf[30];
sprintf (_buf, "%lld", T->left->type_flags);
tl_buf_add_string_q (_buf, -1, 0);
tl_buf_add_string_q ("?", -1, 0);
tl_buf_add_tree (T->right, 0);
return;
}
default:
fprintf (stderr, "%s %s\n", TL_ACT (T->act), TL_TYPE (T->type));
assert (0);
return;
}
}
int tl_count_combinator_name (struct tl_constructor *c) {
assert (c);
tl_buf_reset ();
tl_buf_add_string_nospace (c->real_id ? c->real_id : c->id, -1);
tl_buf_add_tree (c->left, 1);
tl_buf_add_string ("=", -1);
tl_buf_add_tree (c->right, 1);
//fprintf (stderr, "%.*s\n", buf_pos, buf);
if (!c->name) {
c->name = compute_crc32 (buf, buf_pos);
}
return c->name;
}
int tl_print_combinator (struct tl_constructor *c) {
tl_buf_reset ();
tl_buf_add_string_nospace (c->real_id ? c->real_id : c->id, -1);
static char _buf[10];
sprintf (_buf, "#%08x", c->name);
tl_buf_add_string_nospace (_buf, -1);
tl_buf_add_tree (c->left, 1);
tl_buf_add_string ("=", -1);
tl_buf_add_tree (c->right, 1);
if (output_expressions >= 1) {
fprintf (stderr, "%.*s\n", buf_pos, buf);
}
/* if (!c->name) {
c->name = compute_crc32 (buf, buf_pos);
}*/
return c->name;
}
int _tl_finish_subtree (struct tl_combinator_tree *R, int x, long long y) {
assert (R->type == type_type);
assert (R->type_len < 0);
assert (R->act == act_arg || R->act == act_type);
R->type_len = x;
R->type_flags = y;
if (R->act == act_type) {
struct tl_type *t = R->data;
assert (t);
return tl_type_set_params (t, x, y);
}
assert ((R->right->type == type_type && R->right->type_len == 0) || R->right->type == type_num || R->right->type == type_num_value);
return _tl_finish_subtree (R->left, x + 1, y * 2 + (R->right->type == type_num || R->right->type == type_num_value));
}
int tl_finish_subtree (struct tl_combinator_tree *R) {
assert (R);
if (R->type != type_type) {
return 1;
}
if (R->type_len >= 0) {
if (R->type_len > 0) {
TL_ERROR ("Not enough params\n");
return 0;
}
return 1;
}
return _tl_finish_subtree (R, 0, 0);
}
struct tl_combinator_tree *tl_union (struct tl_combinator_tree *L, struct tl_combinator_tree *R) {
if (!L) { return R; }
if (!R) { return L; }
TL_INIT (v);
v = alloc_ctree_node ();
v->left = L;
v->right = R;
switch (L->type) {
case type_num:
if (R->type != type_num_value) {
TL_ERROR ("Union: type mistmatch\n");
return 0;
}
tfree (v, sizeof (*v));
L->type_flags += R->type_flags;
return L;
case type_num_value:
if (R->type != type_num_value && R->type != type_num) {
TL_ERROR ("Union: type mistmatch\n");
return 0;
}
tfree (v, sizeof (*v));
R->type_flags += L->type_flags;
return R;
case type_list_item:
case type_list:
if (R->type != type_list_item) {
TL_ERROR ("Union: type mistmatch\n");
return 0;
}
v->type = type_list;
v->act = act_union;
return v;
case type_type:
if (L->type_len == 0) {
TL_ERROR ("Arguments number exceeds type arity\n");
return 0;
}
if (R->type != type_num && R->type != type_type && R->type != type_num_value) {
TL_ERROR ("Union: type mistmatch\n");
return 0;
}
if (R->type_len < 0) {
if (!tl_finish_subtree (R)) {
return 0;
}
}
if (R->type_len > 0) {
TL_ERROR ("Argument type must have full number of arguments\n");
return 0;
}
if (L->type_len > 0 && ((L->type_flags & 1) != (R->type == type_num || R->type == type_num_value))) {
TL_ERROR ("Argument types mistmatch: L->type_flags = %lld, R->type = %s\n", L->flags, TL_TYPE (R->type));
return 0;
}
v->type = type_type;
v->act = act_arg;
v->type_len = L->type_len > 0 ? L->type_len - 1 : -1;
v->type_flags = L->type_flags >> 1;
return v;
default:
assert (0);
return 0;
}
}
struct tl_combinator_tree *tl_parse_any_term (struct tree *T, int s);
struct tl_combinator_tree *tl_parse_term (struct tree *T, int s) {
assert (T->type == type_term);
int i = 0;
while (i < T->nc && T->c[i]->type == type_percent) { i ++; s ++; }
assert (i < T->nc);
TL_INIT (L);
while (i < T->nc) {
TL_TRY (tl_parse_any_term (T->c[i], s), L);
s = 0;
i ++;
}
return L;
}
struct tl_combinator_tree *tl_parse_type_term (struct tree *T, int s) {
assert (T->type == type_type_term);
assert (T->nc == 1);
struct tl_combinator_tree *Z = tl_parse_term (T->c[0], s);
if (!Z || Z->type != type_type) { if (Z) { TL_ERROR ("type_term: found type %s\n", TL_TYPE (Z->type)); } TL_FAIL; }
return Z;
}
struct tl_combinator_tree *tl_parse_nat_term (struct tree *T, int s) {
assert (T->type == type_nat_term);
assert (T->nc == 1);
struct tl_combinator_tree *Z = tl_parse_term (T->c[0], s);
if (!Z || (Z->type != type_num && Z->type != type_num_value)) { if (Z) { TL_ERROR ("nat_term: found type %s\n", TL_TYPE (Z->type)); }TL_FAIL; }
return Z;
}
struct tl_combinator_tree *tl_parse_subexpr (struct tree *T, int s) {
assert (T->type == type_subexpr);
assert (T->nc >= 1);
int i;
TL_INIT (L);
for (i = 0; i < T->nc; i++) {
TL_TRY (tl_parse_any_term (T->c[i], s), L);
s = 0;
}
return L;
}
struct tl_combinator_tree *tl_parse_expr (struct tree *T, int s) {
assert (T->type == type_expr);
assert (T->nc >= 1);
int i;
TL_INIT (L);
for (i = 0; i < T->nc; i++) {
TL_TRY (tl_parse_subexpr (T->c[i], s), L);
s = 0;
}
return L;
}
struct tl_combinator_tree *tl_parse_nat_const (struct tree *T, int s) {
assert (T->type == type_nat_const);
assert (!T->nc);
if (s > 0) {
TL_ERROR ("Nat const can not preceed with %%\n");
TL_FAIL;
}
assert (T->type == type_nat_const);
assert (!T->nc);
TL_INIT (L);
L = alloc_ctree_node ();
L->act = act_nat_const;
L->type = type_num_value;
int i;
long long x = 0;
for (i = 0; i < T->len; i++) {
x = x * 10 + T->text[i] - '0';
}
L->type_flags = x;
return L;
}
struct tl_combinator_tree *tl_parse_ident (struct tree *T, int s) {
assert (T->type == type_type_ident || T->type == type_var_ident || T->type == type_boxed_type_ident);
assert (!T->nc);
struct tl_var *v = tl_get_var (T->text, T->len);
TL_INIT (L);
if (v) {
L = alloc_ctree_node ();
L->act = act_var;
L->type = v->type ? type_num : type_type;
if (L->type == type_num && s) {
TL_ERROR ("Nat var can not preceed with %%\n");
TL_FAIL;
} else {
if (s) {
L->flags |= 1;
}
}
L->type_len = 0;
L->type_flags = 0;
L->data = v->ptr;
return L;
}
/* if (!mystrcmp2 (T->text, T->len, "#") || !mystrcmp2 (T->text, T->len, "Type")) {
L = alloc_ctree_node ();
L->act = act_type;
L->flags |= 2;
L->data = tl_get_type (T->text, T->len);
assert (L->data);
L->type = type_type;
L->type_len = 0;
L->type_flags = 0;
return L;
}*/
struct tl_constructor *c = tl_get_constructor (T->text, T->len);
if (c) {
assert (c->type);
if (c->type->constructors_num != 1) {
TL_ERROR ("Constructor can be used only if it is the only constructor of the type\n");
return 0;
}
c->type->flags |= 1;
L = alloc_ctree_node ();
L->act = act_type;
L->flags |= 5;
L->data = c->type;
L->type = type_type;
L->type_len = c->type->params_num;
L->type_flags = c->type->params_types;
return L;
}
int x = tl_is_type_name (T->text, T->len);
if (x) {
struct tl_type *t = tl_add_type (T->text, T->len, -1, 0);
L = alloc_ctree_node ();
if (s) {
L->flags |= 1;
t->flags |= 8;
}
L->act = act_type;
L->data = t;
L->type = type_type;
L->type_len = t->params_num;
L->type_flags = t->params_types;
return L;
} else {
TL_ERROR ("Not a type/var ident `%.*s`\n", T->len, T->text);
return 0;
}
}
struct tl_combinator_tree *tl_parse_any_term (struct tree *T, int s) {
switch (T->type) {
case type_type_term:
return tl_parse_type_term (T, s);
case type_nat_term:
return tl_parse_nat_term (T, s);
case type_term:
return tl_parse_term (T, s);
case type_expr:
return tl_parse_expr (T, s);
case type_subexpr:
return tl_parse_subexpr (T, s);
case type_nat_const:
return tl_parse_nat_const (T, s);
case type_type_ident:
case type_var_ident:
return tl_parse_ident (T, s);
default:
fprintf (stderr, "type = %d\n", T->type);
assert (0);
return 0;
}
}
struct tl_combinator_tree *tl_parse_multiplicity (struct tree *T) {
assert (T->type == type_multiplicity);
assert (T->nc == 1);
return tl_parse_nat_term (T->c[0], 0);
}
struct tl_combinator_tree *tl_parse_opt_args (struct tree *T) {
assert (T);
assert (T->type == type_opt_args);
assert (T->nc >= 2);
TL_INIT (R);
TL_TRY (tl_parse_type_term (T->c[T->nc - 1], 0), R);
assert (R->type == type_type && !R->type_len);
assert (tl_finish_subtree (R));
struct tl_type *t = tl_tree_get_type (R);
//assert (t);
int tt = -1;
if (t && !strcmp (t->id, "#")) {
tt = 1;
} else if (t && !strcmp (t->id, "Type")) {
tt = 0;
}
if (tt < 0) {
TL_ERROR ("Optargs can be only of type # or Type\n");
TL_FAIL;
}
int i;
for (i = 0; i < T->nc - 1; i++) {
if (T->c[i]->type != type_var_ident) {
TL_ERROR ("Variable name expected\n");
TL_FAIL;
}
if (T->c[i]->len == 1 && *T->c[i]->text == '_') {
TL_ERROR ("Variables can not be unnamed\n");
TL_FAIL;
}
}
TL_INIT (H);
// for (i = T->nc - 2; i >= (T->nc >= 2 ? 0 : -1); i--) {
for (i = 0; i <= T->nc - 2; i++) {
TL_INIT (S); S = alloc_ctree_node ();
S->left = (i == T->nc - 2) ? R : tl_tree_dup (R) ; S->right = 0;
S->type = type_list_item;
S->type_len = 0;
S->act = act_field;
S->data = i >= 0 ? mystrdup (T->c[i]->text, T->c[i]->len) : 0;
if (tt >= 0) {
assert (S->data);
tl_add_var (S->data, S, tt);
}
S->flags = 33;
H = tl_union (H, S);
}
return H;
}
struct tl_combinator_tree *tl_parse_args (struct tree *T);
struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
assert (T);
assert (T->type == type_args2);
assert (T->nc >= 1);
TL_INIT (R);
TL_INIT (L);
int x = 0;
char *field_name = 0;
if (T->c[x]->type == type_var_ident_opt || T->c[x]->type == type_var_ident) {
field_name = mystrdup (T->c[x]->text, T->c[x]->len);
if (!tl_add_field (field_name)) {
TL_ERROR ("Duplicate field name %s\n", field_name);
TL_FAIL;
}
x ++;
}
//fprintf (stderr, "%d %d\n", x, T->nc);
if (T->c[x]->type == type_multiplicity) {
L = tl_parse_multiplicity (T->c[x]);
if (!L) { TL_FAIL;}
x ++;
} else {
struct tl_var *v = tl_get_last_num_var ();
if (!v) {
TL_ERROR ("Expected multiplicity or nat var\n");
TL_FAIL;
}
L = alloc_ctree_node ();
L->act = act_var;
L->type = type_num;
L->flags |= 128;
L->type_len = 0;
L->type_flags = 0;
L->data = v->ptr;
((struct tl_combinator_tree *)(v->ptr))->flags |= 256;
}
namespace_push ();
while (x < T->nc) {
TL_TRY (tl_parse_args (T->c[x]), R);
x ++;
}
namespace_pop ();
struct tl_combinator_tree *S = alloc_ctree_node ();
S->type = type_type;
S->type_len = 0;
S->act = act_array;
S->left = L;
S->right = R;
//S->data = field_name;
struct tl_combinator_tree *H = alloc_ctree_node ();
H->type = type_list_item;
H->act = act_field;
H->left = S;
H->right = 0;
H->data = field_name;
H->type_len = 0;
return H;
}
void tl_mark_vars (struct tl_combinator_tree *T);
struct tl_combinator_tree *tl_parse_args134 (struct tree *T) {
assert (T);
assert (T->type == type_args1 || T->type == type_args3 || T->type == type_args4);
assert (T->nc >= 1);
TL_INIT (R);
TL_TRY (tl_parse_type_term (T->c[T->nc - 1], 0), R);
assert (tl_finish_subtree (R));
assert (R->type == type_type && !R->type_len);
struct tl_type *t = tl_tree_get_type (R);
//assert (t);
int tt = -1;
if (t && !strcmp (t->id, "#")) {
tt = 1;
} else if (t && !strcmp (t->id, "Type")) {
tt = 0;
}
/* if (tt >= 0 && T->nc == 1) {
TL_ERROR ("Variables can not be unnamed (type %d)\n", tt);
}*/
int last = T->nc - 2;
int excl = 0;
if (last >= 0 && T->c[last]->type == type_exclam) {
excl ++;
tl_mark_vars (R);
last --;
}
if (last >= 0 && T->c[last]->type == type_optional_arg_def) {
assert (T->c[last]->nc == 2);
TL_INIT (E); E = alloc_ctree_node ();
E->type = type_type;
E->act = act_opt_field;
E->left = tl_parse_ident (T->c[last]->c[0], 0);
int i;
long long x = 0;
for (i = 0; i < T->c[last]->c[1]->len; i++) {
x = x * 10 + T->c[last]->c[1]->text[i] - '0';
}
E->left->type_flags = x;
E->type_flags = R->type_flags;
E->type_len = R->type_len;
E->right = R;
R = E;
last --;
}
int i;
for (i = 0; i < last; i++) {
if (T->c[i]->type != type_var_ident && T->c[i]->type != type_var_ident_opt) {
TL_ERROR ("Variable name expected\n");
TL_FAIL;
}
/* if (tt >= 0 && (T->nc == 1 || (T->c[i]->len == 1 && *T->c[i]->text == '_'))) {
TL_ERROR ("Variables can not be unnamed\n");
TL_FAIL;
}*/
}
TL_INIT (H);
// for (i = T->nc - 2; i >= (T->nc >= 2 ? 0 : -1); i--) {
for (i = (last >= 0 ? 0 : -1); i <= last; i++) {
TL_INIT (S); S = alloc_ctree_node ();
S->left = (i == last) ? R : tl_tree_dup (R) ; S->right = 0;
S->type = type_list_item;
S->type_len = 0;
S->act = act_field;
S->data = i >= 0 ? mystrdup (T->c[i]->text, T->c[i]->len) : 0;
if (excl) {
S->flags |= FLAG_EXCL;
}
if (S->data && (T->c[i]->len >= 2 || *T->c[i]->text != '_')) {
if (!tl_add_field (S->data)) {
TL_ERROR ("Duplicate field name %s\n", (char *)S->data);
TL_FAIL;
}
}
if (tt >= 0) {
//assert (S->data);
char *name = S->data;
if (!name) {
static char s[20];
sprintf (s, "%lld", lrand48 () * (1ll << 32) + lrand48 ());
name = s;
}
struct tl_var *v = tl_add_var (name, S, tt);
if (!v) {TL_FAIL;}
v->flags |= 2;
}
H = tl_union (H, S);
}
return H;
}
struct tl_combinator_tree *tl_parse_args (struct tree *T) {
assert (T->type == type_args);
assert (T->nc == 1);
switch (T->c[0]->type) {
case type_args1:
return tl_parse_args134 (T->c[0]);
case type_args2:
return tl_parse_args2 (T->c[0]);
case type_args3:
return tl_parse_args134 (T->c[0]);
case type_args4:
return tl_parse_args134 (T->c[0]);
default:
assert (0);
return 0;
}
}
void tl_mark_vars (struct tl_combinator_tree *T) {
if (!T) { return; }
if (T->act == act_var) {
char *id = ((struct tl_combinator_tree *)(T->data))->data;
struct tl_var *v = tl_get_var (id, strlen (id));
assert (v);
v->flags |= 1;
}
tl_mark_vars (T->left);
tl_mark_vars (T->right);
}
struct tl_combinator_tree *tl_parse_result_type (struct tree *T) {
assert (T->type == type_result_type);
assert (T->nc >= 1);
assert (T->nc <= 64);
TL_INIT (L);
if (tl_get_var (T->c[0]->text, T->c[0]->len)) {
if (T->nc != 1) {
TL_ERROR ("Variable can not take params\n");
TL_FAIL;
}
L = alloc_ctree_node ();
L->act = act_var;
L->type = type_type;
struct tl_var *v = tl_get_var (T->c[0]->text, T->c[0]->len);
if (v->type) {
TL_ERROR ("Type mistmatch\n");
TL_FAIL;
}
L->data = v->ptr;
// assert (v->ptr);
} else {
L = alloc_ctree_node ();
L->act = act_type;
L->type = type_type;
struct tl_type *t = tl_add_type (T->c[0]->text, T->c[0]->len, -1, 0);
assert (t);
L->type_len = t->params_num;
L->type_flags = t->params_types;
L->data = t;
int i;
for (i = 1; i < T->nc; i++) {
TL_TRY (tl_parse_any_term (T->c[i], 0), L);
assert (L->right);
assert (L->right->type == type_num || L->right->type == type_num_value || (L->right->type == type_type && L->right->type_len == 0));
}
}
if (!tl_finish_subtree (L)) {
TL_FAIL;
}
tl_mark_vars (L);
return L;
}
int __ok;
void tl_var_check_used (struct tl_var *v) {
__ok = __ok && (v->flags & 3);
}
int tl_parse_combinator_decl (struct tree *T, int fun) {
assert (T->type == type_combinator_decl);
assert (T->nc >= 3);
namespace_level = 0;
tl_clear_vars ();
tl_clear_fields ();
TL_INIT (L);
TL_INIT (R);
int i = 1;
while (i < T->nc - 2 && T->c[i]->type == type_opt_args) {
TL_TRY (tl_parse_opt_args (T->c[i]), L);
i++;
}
while (i < T->nc - 2 && T->c[i]->type == type_args) {
TL_TRY (tl_parse_args (T->c[i]), L);
i++;
}
assert (i == T->nc - 2 && T->c[i]->type == type_equals);
i ++;
R = tl_parse_result_type (T->c[i]);
if (!R) { TL_FAIL; }
struct tl_type *t = tl_tree_get_type (R);
if (!fun && !t) {
TL_ERROR ("Only functions can return variables\n");
}
assert (t || fun);
assert (namespace_level == 0);
__ok = 1;
tree_act_tl_var (vars[0], tl_var_check_used);
if (!__ok) {
TL_ERROR ("Not all variables are used in right side\n");
TL_FAIL;
}
if (tl_get_constructor (T->c[0]->text, T->c[0]->len) || tl_get_function (T->c[0]->text, T->c[0]->len)) {
TL_ERROR ("Duplicate combinator id %.*s\n", T->c[0]->len, T->c[0]->text);
return 0;
}
struct tl_constructor *c = !fun ? tl_add_constructor (t, T->c[0]->text, T->c[0]->len, 0) : tl_add_function (t, T->c[0]->text, T->c[0]->len, 0);
if (!c) { TL_FAIL; }
c->left = L;
c->right = R;
if (!c->name) {
tl_count_combinator_name (c);
}
tl_print_combinator (c);
return 1;
}
void change_var_ptrs (struct tl_combinator_tree *O, struct tl_combinator_tree *D, struct tree_var_value **V) {
if (!O || !D) {
assert (!O && !D);
return;
}
if (O->act == act_field) {
struct tl_type *t = tl_tree_get_type (O->left);
if (t && (!strcmp (t->id, "#") || !strcmp (t->id, "Type"))) {
tl_set_var_value (V, O, D);
}
}
if (O->act == act_var) {
assert (D->data == O->data);
D->data = tl_get_var_value (V, O->data);
assert (D->data);
}
change_var_ptrs (O->left, D->left, V);
change_var_ptrs (O->right, D->right, V);
}
struct tl_combinator_tree *change_first_var (struct tl_combinator_tree *O, struct tl_combinator_tree **X, struct tl_combinator_tree *Y) {
if (!O) { return (void *)-2l; };
if (O->act == act_field && !*X) {
struct tl_type *t = tl_tree_get_type (O->left);
if (t && !strcmp (t->id, "#")) {
if (Y->type != type_num && Y->type != type_num_value) {
TL_ERROR ("change_var: Type mistmatch\n");
return 0;
} else {
*X = O;
return (void *)-1l;
}
}
if (t && !strcmp (t->id, "Type")) {
if (Y->type != type_type || Y->type_len != 0) {
TL_ERROR ("change_var: Type mistmatch\n");
return 0;
} else {
*X = O;
return (void *)-1l;
}
}
}
if (O->act == act_var) {
if (O->data == *X) {
struct tl_combinator_tree *R = tl_tree_dup (Y);
if (O->type == type_num || O->type == type_num_value) { R->type_flags += O->type_flags; }
return R;
}
}
struct tl_combinator_tree *t;
t = change_first_var (O->left, X, Y);
if (!t) { return 0;}
if (t == (void *)-1l) {
t = change_first_var (O->right, X, Y);
if (!t) { return 0;}
if (t == (void *)-1l) { return (void *)-1l; }
if (t != (void *)-2l) { return t;}
return (void *)-1l;
}
if (t != (void *)-2l) {
O->left = t;
}
t = change_first_var (O->right, X, Y);
if (!t) { return 0;}
if (t == (void *)-1l) {
return O->left;
}
if (t != (void *)-2l) {
O->right = t;
}
return O;
}
int uniformize (struct tl_combinator_tree *L, struct tl_combinator_tree *R, struct tree_var_value **T);
struct tree_var_value **_T;
int __tok;
void check_nat_val (struct tl_var_value v) {
if (!__tok) { return; }
long long x = v.num_val;
struct tl_combinator_tree *L = v.val;
if (L->type == type_type) { return;}
while (1) {
if (L->type == type_num_value) {
if (x + L->type_flags < 0) {
__tok = 0;
return;
} else {
return;
}
}
assert (L->type == type_num);
x += L->type_flags;
x += tl_get_var_value_num (_T, L->data);
L = tl_get_var_value (_T, L->data);
if (!L) { return;}
}
}
int check_constructors_equal (struct tl_combinator_tree *L, struct tl_combinator_tree *R, struct tree_var_value **T) {
if (!uniformize (L, R, T)) { return 0; }
__tok = 1;
_T = T;
tree_act_var_value (*T, check_nat_val);
return __tok;
}
struct tl_combinator_tree *reduce_type (struct tl_combinator_tree *A, struct tl_type *t) {
assert (A);
if (A->type_len == t->params_num) {
assert (A->type_flags == t->params_types);
A->act = act_type;
A->type = type_type;
A->left = A->right = 0;
A->data = t;
return A;
}
A->left = reduce_type (A->left, t);
return A;
}
struct tl_combinator_tree *change_value_var (struct tl_combinator_tree *O, struct tree_var_value **X) {
if (!O) { return (void *)-2l; };
while (O->act == act_var) {
assert (O->data);
if (!tl_get_var_value (X, O->data)) {
break;
}
if (O->type == type_type) {
O = tl_tree_dup (tl_get_var_value (X, O->data));
} else {
long long n = tl_get_var_value_num (X, O->data);
struct tl_combinator_tree *T = tl_get_var_value (X, O->data);
O->data = T->data;
O->type = T->type;
O->act = T->act;
O->type_flags = O->type_flags + n + T->type_flags;
}
}
if (O->act == act_field) {
if (tl_get_var_value (X, O)) { return (void *)-1l; }
}
struct tl_combinator_tree *t;
t = change_value_var (O->left, X);
if (!t) { return 0;}
if (t == (void *)-1l) {
t = change_value_var (O->right, X);
if (!t) { return 0;}
if (t == (void *)-1l) { return (void *)-1l; }
if (t != (void *)-2l) { return t;}
return (void *)-1l;
}
if (t != (void *)-2l) {
O->left = t;
}
t = change_value_var (O->right, X);
if (!t) { return 0;}
if (t == (void *)-1l) {
return O->left;
}
if (t != (void *)-2l) {
O->right = t;
}
return O;
}
int tl_parse_partial_type_app_decl (struct tree *T) {
assert (T->type == type_partial_type_app_decl);
assert (T->nc >= 1);
assert (T->c[0]->type == type_boxed_type_ident);
struct tl_type *t = tl_get_type (T->c[0]->text, T->c[0]->len);
if (!t) {
TL_ERROR ("Can not make partial app for unknown type\n");
return 0;
}
tl_type_finalize (t);
struct tl_combinator_tree *L = tl_parse_ident (T->c[0], 0);
assert (L);
int i;
tl_buf_reset ();
int cc = T->nc - 1;
for (i = 1; i < T->nc; i++) {
TL_TRY (tl_parse_any_term (T->c[i], 0), L);
tl_buf_add_tree (L->right, 1);
}
while (L->type_len) {
struct tl_combinator_tree *C = alloc_ctree_node ();
C->act = act_var;
C->type = (L->type_flags & 1) ? type_num : type_type;
C->type_len = 0;
C->type_flags = 0;
C->data = (void *)-1l;
L = tl_union (L, C);
if (!L) { return 0; }
}
static char _buf[100000];
snprintf (_buf, 100000, "%s%.*s", t->id, buf_pos, buf);
struct tl_type *nt = tl_add_type (_buf, strlen (_buf), t->params_num - cc, t->params_types >> cc);
assert (nt);
//snprintf (_buf, 100000, "%s #", t->id);
//nt->real_id = strdup (_buf);
for (i = 0; i < t->constructors_num; i++) {
struct tl_constructor *c = t->constructors[i];
struct tree_var_value *V = 0;
TL_INIT (A);
TL_INIT (B);
A = tl_tree_dup (c->left);
B = tl_tree_dup (c->right);
struct tree_var_value *W = 0;
change_var_ptrs (c->left, A, &W);
change_var_ptrs (c->right, B, &W);
if (!check_constructors_equal (B, L, &V)) { continue; }
B = reduce_type (B, nt);
A = change_value_var (A, &V);
if (A == (void *)-1l) { A = 0;}
B = change_value_var (B, &V);
assert (B != (void *)-1l);
snprintf (_buf, 100000, "%s%.*s", c->id, buf_pos, buf);
struct tl_constructor *r = tl_add_constructor (nt, _buf, strlen (_buf), 1);
snprintf (_buf, 100000, "%s", c->id);
r->real_id = tstrdup (_buf);
r->left = A;
r->right = B;
if (!r->name) {
tl_count_combinator_name (r);
}
tl_print_combinator (r);
}
return 1;
}
int tl_parse_partial_comb_app_decl (struct tree *T, int fun) {
assert (T->type == type_partial_comb_app_decl);
struct tl_constructor *c = !fun ? tl_get_constructor (T->c[0]->text, T->c[0]->len) : tl_get_function (T->c[0]->text, T->c[0]->len);
if (!c) {
TL_ERROR ("Can not make partial app for undefined combinator\n");
return 0;
}
//TL_INIT (K);
//static char buf[1000];
//int x = sprintf (buf, "%s", c->id);
TL_INIT (L);
TL_INIT (R);
L = tl_tree_dup (c->left);
R = tl_tree_dup (c->right);
struct tree_var_value *V = 0;
change_var_ptrs (c->left, L, &V);
change_var_ptrs (c->right, R, &V);
V = tree_clear_var_value (V);
int i;
tl_buf_reset ();
for (i = 1; i < T->nc; i++) {
TL_INIT (X);
TL_INIT (Z);
X = tl_parse_any_term (T->c[i], 0);
struct tl_combinator_tree *K = 0;
if (!(Z = change_first_var (L, &K, X))) {
TL_FAIL;
}
L = Z;
if (!K) {
TL_ERROR ("Partial app: not enougth variables (i = %d)\n", i);
TL_FAIL;
}
if (!(Z = change_first_var (R, &K, X))) {
TL_FAIL;
}
assert (Z == R);
tl_buf_add_tree (X, 1);
}
static char _buf[100000];
snprintf (_buf, 100000, "%s%.*s", c->id, buf_pos, buf);
// fprintf (stderr, "Local id: %s\n", _buf);
struct tl_constructor *r = !fun ? tl_add_constructor (c->type, _buf, strlen (_buf), 1) : tl_add_function (c->type, _buf, strlen (_buf), 1);
r->left = L;
r->right = R;
snprintf (_buf, 100000, "%s", c->id);
r->real_id = tstrdup (_buf);
if (!r->name) {
tl_count_combinator_name (r);
}
tl_print_combinator (r);
return 1;
}
int tl_parse_partial_app_decl (struct tree *T, int fun) {
assert (T->type == type_partial_app_decl);
assert (T->nc == 1);
if (T->c[0]->type == type_partial_comb_app_decl) {
return tl_parse_partial_comb_app_decl (T->c[0], fun);
} else {
if (fun) {
TL_ERROR ("Partial type app in functions block\n");
TL_FAIL;
}
return tl_parse_partial_type_app_decl (T->c[0]);
}
}
int tl_parse_final_final (struct tree *T) {
assert (T->type == type_final_final);
assert (T->nc == 1);
struct tl_type *R;
if ((R = tl_get_type (T->c[0]->text, T->c[0]->len))) {
R->flags |= 1;
return 1;
} else {
TL_ERROR ("Final statement for type `%.*s` before declaration\n", T->c[0]->len, T->c[0]->text);
TL_FAIL;
}
}
int tl_parse_final_new (struct tree *T) {
assert (T->type == type_final_new);
assert (T->nc == 1);
if (tl_get_type (T->c[0]->text, T->c[0]->len)) {
TL_ERROR ("New statement: type `%.*s` already declared\n", T->c[0]->len, T->c[0]->text);
TL_FAIL;
} else {
return 1;
}
}
int tl_parse_final_empty (struct tree *T) {
assert (T->type == type_final_empty);
assert (T->nc == 1);
if (tl_get_type (T->c[0]->text, T->c[0]->len)) {
TL_ERROR ("New statement: type `%.*s` already declared\n", T->c[0]->len, T->c[0]->text);
TL_FAIL;
}
struct tl_type *t = tl_add_type (T->c[0]->text, T->c[0]->len, 0, 0);
assert (t);
t->flags |= 1 | FLAG_EMPTY;
return 1;
}
int tl_parse_final_decl (struct tree *T, int fun) {
assert (T->type == type_final_decl);
assert (!fun);
assert (T->nc == 1);
switch (T->c[0]->type) {
case type_final_new:
return tl_parse_final_new (T->c[0]);
case type_final_final:
return tl_parse_final_final (T->c[0]);
case type_final_empty:
return tl_parse_final_empty (T->c[0]);
default:
assert (0);
return 0;
}
}
int tl_parse_builtin_combinator_decl (struct tree *T, int fun) {
if (fun) {
TL_ERROR ("Builtin type can not be described in function block\n");
return -1;
}
assert (T->type == type_builtin_combinator_decl);
assert (T->nc == 2);
assert (T->c[0]->type == type_full_combinator_id);
assert (T->c[1]->type == type_boxed_type_ident);
if ((!mystrcmp2 (T->c[0]->text, T->c[0]->len, "int") && !mystrcmp2 (T->c[1]->text, T->c[1]->len, "Int")) ||
(!mystrcmp2 (T->c[0]->text, T->c[0]->len, "long") && !mystrcmp2 (T->c[1]->text, T->c[1]->len, "Long")) ||
(!mystrcmp2 (T->c[0]->text, T->c[0]->len, "double") && !mystrcmp2 (T->c[1]->text, T->c[1]->len, "Double")) ||
(!mystrcmp2 (T->c[0]->text, T->c[0]->len, "string") && !mystrcmp2 (T->c[1]->text, T->c[1]->len, "String"))) {
struct tl_type *t = tl_add_type (T->c[1]->text, T->c[1]->len, 0, 0);
if (!t) {
return 0;
}
struct tl_constructor *c = tl_add_constructor (t, T->c[0]->text, T->c[0]->len, 0);
if (!c) {
return 0;
}
c->left = alloc_ctree_node ();
c->left->act = act_question_mark;
c->left->type = type_list_item;
c->right = alloc_ctree_node ();
c->right->act = act_type;
c->right->data = t;
c->right->type = type_type;
if (!c->name) {
tl_count_combinator_name (c);
}
tl_print_combinator (c);
} else {
TL_ERROR ("Unknown builting type `%.*s`\n", T->c[0]->len, T->c[0]->text);
return 0;
}
return 1;
}
int tl_parse_declaration (struct tree *T, int fun) {
assert (T->type == type_declaration);
assert (T->nc == 1);
switch (T->c[0]->type) {
case type_combinator_decl:
return tl_parse_combinator_decl (T->c[0], fun);
case type_partial_app_decl:
return tl_parse_partial_app_decl (T->c[0], fun);
case type_final_decl:
return tl_parse_final_decl (T->c[0], fun);
case type_builtin_combinator_decl:
return tl_parse_builtin_combinator_decl (T->c[0], fun);
default:
assert (0);
return 0;
}
}
int tl_parse_constr_declarations (struct tree *T) {
assert (T->type == type_constr_declarations);
int i;
for (i = 0; i < T->nc; i++) {
TL_TRY_PES (tl_parse_declaration (T->c[i], 0));
}
return 1;
}
int tl_parse_fun_declarations (struct tree *T) {
assert (T->type == type_fun_declarations);
int i;
for (i = 0; i < T->nc; i++) {
TL_TRY_PES (tl_parse_declaration (T->c[i], 1));
}
return 1;
}
int tl_tree_lookup_value (struct tl_combinator_tree *L, void *var, struct tree_var_value **T) {
if (!L) {
return -1;
}
if (L->act == act_var && L->data == var) {
return 0;
}
if (L->act == act_var) {
struct tl_combinator_tree *E = tl_get_var_value (T, L->data);
if (!E) { return -1;}
else { return tl_tree_lookup_value (E, var, T); }
}
if (tl_tree_lookup_value (L->left, var, T) >= 0) { return 1; }
if (tl_tree_lookup_value (L->right, var, T) >= 0) { return 1; }
return -1;
}
int tl_tree_lookup_value_nat (struct tl_combinator_tree *L, void *var, long long x, struct tree_var_value **T) {
assert (L);
if (L->type == type_num_value) { return -1; }
assert (L->type == type_num);
assert (L->act == act_var);
if (L->data == var) {
return x == L->type_flags ? 0 : 1;
} else {
if (!tl_get_var_value (T, L->data)) {
return -1;
}
return tl_tree_lookup_value_nat (tl_get_var_value (T, L->data), var, x + tl_get_var_value_num (T, L->data), T);
}
}
int uniformize (struct tl_combinator_tree *L, struct tl_combinator_tree *R, struct tree_var_value **T) {
if (!L || !R) {
assert (!L && !R);
return 1;
}
if (R->act == act_var) {
struct tl_combinator_tree *_ = R; R = L; L = _;
}
if (L->type == type_type) {
if (R->type != type_type || L->type_len != R->type_len || L->type_flags != R->type_flags) {
return 0;
}
if (R->data == (void *)-1l || L->data == (void *)-1l) { return 1;}
if (L->act == act_var) {
int x = tl_tree_lookup_value (R, L->data, T);
if (x > 0) {
// if (tl_tree_lookup_value (R, L->data, T) > 0) {
return 0;
}
if (x == 0) {
return 1;
}
struct tl_combinator_tree *E = tl_get_var_value (T, L->data);
if (!E) {
tl_set_var_value (T, L->data, R);
return 1;
} else {
return uniformize (E, R, T);
}
} else {
if (L->act != R->act || L->data != R->data) {
return 0;
}
return uniformize (L->left, R->left, T) && uniformize (L->right, R->right, T);
}
} else {
assert (L->type == type_num || L->type == type_num_value);
if (R->type != type_num && R->type != type_num_value) {
return 0;
}
assert (R->type == type_num || R->type == type_num_value);
if (R->data == (void *)-1l || L->data == (void *)-1l) { return 1;}
long long x = 0;
struct tl_combinator_tree *K = L;
while (1) {
x += K->type_flags;
if (K->type == type_num_value) {
break;
}
if (!tl_get_var_value (T, K->data)) {
int s = tl_tree_lookup_value_nat (R, K->data, K->type_flags, T);
if (s > 0) {
return 0;
}
if (s == 0) {
return 1;
}
/*tl_set_var_value_num (T, K->data, R, -x);
return 1;*/
break;
}
x += tl_get_var_value_num (T, K->data);
K = tl_get_var_value (T, K->data);
}
long long y = 0;
struct tl_combinator_tree *M = R;
while (1) {
y += M->type_flags;
if (M->type == type_num_value) {
break;
}
if (!tl_get_var_value (T, M->data)) {
int s = tl_tree_lookup_value_nat (L, M->data, M->type_flags, T);
if (s > 0) {
return 0;
}
if (s == 0) {
return 1;
}
/*tl_set_var_value_num (T, M->data, L, -y);
return 1;*/
break;
}
y += tl_get_var_value_num (T, M->data);
M = tl_get_var_value (T, M->data);
}
if (K->type == type_num_value && M->type == type_num_value) {
return x == y;
}
if (M->type == type_num_value) {
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags));
return 1;
} else if (K->type == type_num_value) {
tl_set_var_value_num (T, M->data, K, -(y - x + K->type_flags));
return 1;
} else {
if (x >= y) {
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags));
} else {
tl_set_var_value_num (T, M->data, K, -(y - x + K->type_flags));
}
return 1;
}
}
return 0;
}
void tl_type_check (struct tl_type *t) {
if (!__ok) return;
if (!strcmp (t->id, "#")) { t->name = 0x70659eff; return; }
if (!strcmp (t->id, "Type")) { t->name = 0x2cecf817; return; }
if (t->constructors_num <= 0 && !(t->flags & FLAG_EMPTY)) {
TL_ERROR ("Type %s has no constructors\n", t->id);
__ok = 0;
return;
}
int i, j;
t->name = 0;
for (i = 0; i < t->constructors_num; i++) {
t->name ^= t->constructors[i]->name;
}
for (i = 0; i < t->constructors_num; i++) {
for (j = i + 1; j < t->constructors_num; j++) {
struct tree_var_value *v = 0;
if (check_constructors_equal (t->constructors[i]->right, t->constructors[j]->right, &v)) {
t->flags |= 16;
}
}
}
if ((t->flags & 24) == 24) {
TL_WARNING ("Warning: Type %s has overlapping costructors, but it is used with `%%`\n", t->id);
}
int z = 0;
int sid = 0;
for (i = 0; i < t->constructors_num; i++) if (*t->constructors[i]->id == '_') {
z ++;
sid = i;
}
if (z > 1) {
TL_ERROR ("Type %s has %d default constructors\n", t->id, z);
__ok = 0;
return;
}
if (z == 1 && (t->flags & 8)) {
TL_ERROR ("Type %s has default constructors and used bare\n", t->id);
__ok = 0;
return;
}
if (z) {
struct tl_constructor *c;
c = t->constructors[sid];
t->constructors[sid] = t->constructors[t->constructors_num - 1];
t->constructors[t->constructors_num - 1] = c;
}
}
struct tl_program *tl_parse (struct tree *T) {
assert (T);
assert (T->type == type_tl_program);
int i;
tl_program_cur = talloc (sizeof (*tl_program_cur));
tl_add_type ("#", 1, 0, 0);
tl_add_type ("Type", 4, 0, 0);
for (i = 0; i < T->nc; i++) {
if (T->c[i]->type == type_constr_declarations) { TL_TRY_PES (tl_parse_constr_declarations (T->c[i])); }
else { TL_TRY_PES (tl_parse_fun_declarations (T->c[i])) }
}
__ok = 1;
tree_act_tl_type (tl_type_tree, tl_type_check);
if (!__ok) {
return 0;
}
return tl_program_cur;
}
int __f;
int num = 0;
void wint (int a) {
// printf ("%d ", a);
assert (write (__f, &a, 4) == 4);
}
void wdata (const void *x, int len) {
assert (write (__f, x, len) == len);
}
void wstr (const char *s) {
if (s) {
// printf ("\"%s\" ", s);
if (schema_version < 1) {
wint (strlen (s));
wdata (s, strlen (s));
} else {
int x = strlen (s);
if (x <= 254) {
assert (write (__f, &x, 1) == 1);
} else {
fprintf (stderr, "String is too big...\n");
assert (0);
}
wdata (s, x);
x ++;
int t = 0;
if (x & 3) {
wdata (&t, 4 - (x & 3));
}
}
} else {
// printf ("<none> ");
wint (0);
}
}
void wll (long long a) {
// printf ("%lld ", a);
assert (write (__f, &a, 8) == 8);
}
int count_list_size (struct tl_combinator_tree *T) {
assert (T->type == type_list || T->type == type_list_item);
if (T->type == type_list_item) {
return 1;
} else {
return count_list_size (T->left) + count_list_size (T->right);
}
}
void write_type_flags (long long flags) {
int new_flags = 0;
if (flags & 1) {
new_flags |= FLAG_BARE;
}
if (flags & FLAG_DEFAULT_CONSTRUCTOR) {
new_flags |= FLAG_DEFAULT_CONSTRUCTOR;
}
wint (new_flags);
}
void write_field_flags (long long flags) {
int new_flags = 0;
//fprintf (stderr, "%lld\n", flags);
if (flags & 1) {
new_flags |= FLAG_BARE;
}
if (flags & 32) {
new_flags |= FLAG_OPT_VAR;
}
if (flags & FLAG_EXCL) {
new_flags |= FLAG_EXCL;
}
if (flags & FLAG_OPT_FIELD) {
// new_flags |= FLAG_OPT_FIELD;
new_flags |= 2;
}
if (flags & (1 << 21)) {
new_flags |= 4;
}
wint (new_flags);
}
void write_var_type_flags (long long flags) {
int new_flags = 0;
if (flags & 1) {
new_flags |= FLAG_BARE;
}
if (new_flags & FLAG_BARE) {
TL_ERROR ("Sorry, bare vars are not (yet ?) supported.\n");
assert (!(new_flags & FLAG_BARE));
}
wint (new_flags);
}
void write_tree (struct tl_combinator_tree *T, int extra, struct tree_var_value **v, int *last_var);
void write_args (struct tl_combinator_tree *T, struct tree_var_value **v, int *last_var) {
assert (T->type == type_list || T->type == type_list_item);
if (T->type == type_list) {
assert (T->act == act_union);
assert (T->left);
assert (T->right);
write_args (T->left, v, last_var);
write_args (T->right, v, last_var);
return;
}
if (schema_version == 1) {
wint (TLS_ARG);
} if (schema_version == 2) {
wint (TLS_ARG_V2);
} else {
wint (-3);
}
if (T->act == act_question_mark) {
if (schema_version >= 1) {
assert (0);
} else {
wint (-100);
}
return;
}
if (schema_version >= 1) {
} else {
wint (-99);
}
assert (T->act == act_field);
assert (T->left);
wstr (T->data && strcmp (T->data, "_") ? T->data : 0);
long long f = T->flags;
if (T->left->act == act_opt_field) {
f |= (1 << 20);
}
if (T->left->act == act_type && T->left->data && (!strcmp (((struct tl_type *)T->left->data)->id, "#") || !strcmp (((struct tl_type *)T->left->data)->id, "Type"))) {
write_field_flags (f | (1 << 21));
wint (*last_var);
*last_var = (*last_var) + 1;
tl_set_var_value_num (v, T, 0, (*last_var) - 1);
} else {
write_field_flags (f);
if (schema_version <= 1) {
wint (-1);
}
}
write_tree (T->left, 0, v, last_var);
}
void write_array (struct tl_combinator_tree *T, struct tree_var_value **v, int *last_var) {
if (schema_version == 1) {
wint (TLS_TREE_ARRAY);
} else if (schema_version == 2) {
wint (TLS_ARRAY);
} else {
wint (-8);
}
write_tree (T->left, 0, v, last_var);
write_tree (T->right, 0, v, last_var);
}
void write_type_rec (struct tl_combinator_tree *T, int cc, struct tree_var_value **v, int *last_var) {
if (T->act == act_arg) {
write_type_rec (T->left, cc + 1, v, last_var);
if (schema_version >= 2) {
if (T->right->type == type_num_value || T->right->type == type_num) {
wint (TLS_EXPR_NAT);
} else {
wint (TLS_EXPR_TYPE);
}
}
write_tree (T->right, 0, v, last_var);
} else {
assert (T->act == act_var || T->act == act_type);
if (T->act == act_var) {
assert (!cc);
if (schema_version == 1) {
wint (TLS_TREE_TYPE_VAR);
} else if (schema_version == 2) {
wint (TLS_TYPE_VAR);
} else {
wint (-6);
}
wint (tl_get_var_value_num (v, T->data));
write_var_type_flags (T->flags);
//wint (T->flags);
} else {
if (schema_version == 1) {
wint (TLS_TREE_TYPE);
} else if (schema_version == 2) {
wint (TLS_TYPE_EXPR);
} else {
wint (-7);
}
struct tl_type *t = T->data;
wint (t->name);
write_type_flags (T->flags);
// wint (T->flags);
wint (cc);
// fprintf (stderr, "cc = %d\n", cc);
}
}
}
void write_opt_type (struct tl_combinator_tree *T, struct tree_var_value **v, int *last_var) {
if (schema_version >= 1) {
} else {
wint (-20);
}
wint (tl_get_var_value_num (v, T->left->data));
wint (T->left->type_flags);
// write_tree (T->right, 0, v, last_var);
assert (T);
T = T->right;
switch (T->type) {
case type_type:
if (T->act == act_array) {
write_array (T, v, last_var);
} else if (T->act == act_type || T->act == act_var || T->act == act_arg) {
write_type_rec (T, 0, v, last_var);
} else {
assert (0);
}
break;
default:
assert (0);
}
}
void write_tree (struct tl_combinator_tree *T, int extra, struct tree_var_value **v, int *last_var) {
assert (T);
switch (T->type) {
case type_list_item:
case type_list:
if (schema_version >= 1) {
if (extra) {
wint (schema_version >= 2 ? TLS_COMBINATOR_RIGHT_V2 : TLS_COMBINATOR_RIGHT);
}
} else {
wint (extra ? -1 : -2);
}
wint (count_list_size (T));
write_args (T, v, last_var);
break;
case type_num_value:
wint (schema_version >= 1 ? schema_version >= 2 ? (int)TLS_NAT_CONST : (int)TLS_TREE_NAT_CONST : -4);
if (schema_version >= 2) {
wint (T->type_flags);
} else {
wll (T->type_flags);
}
break;
case type_num:
wint (schema_version >= 1 ? schema_version >= 2 ? (int)TLS_NAT_VAR : (int)TLS_TREE_NAT_VAR : -5);
if (schema_version >= 2) {
wint (T->type_flags);
} else {
wll (T->type_flags);
}
wint (tl_get_var_value_num (v, T->data));
break;
case type_type:
if (T->act == act_array) {
write_array (T, v, last_var);
} else if (T->act == act_type || T->act == act_var || T->act == act_arg) {
write_type_rec (T, 0, v, last_var);
} else {
assert (T->act == act_opt_field);
write_opt_type (T, v, last_var);
}
break;
default:
assert (0);
}
}
void write_type (struct tl_type *t) {
wint (schema_version >= 1 ? TLS_TYPE : 1);
wint (t->name);
wstr (t->id);
wint (t->constructors_num);
wint (t->flags);
wint (t->params_num);
wll (t->params_types);
}
int is_builtin_type (const char *id) {
return !strcmp (id, "int") || !strcmp (id, "long") || !strcmp (id, "double") || !strcmp (id, "string");
}
void write_combinator (struct tl_constructor *c) {
wint (c->name);
wstr (c->id);
wint (c->type ? c->type->name : 0);
struct tree_var_value *T = 0;
int x = 0;
assert (c->right);
if (c->left) {
if (schema_version >= 1 && is_builtin_type (c->id)) {
wint (TLS_COMBINATOR_LEFT_BUILTIN);
} else {
if (schema_version >= 1) {
wint (TLS_COMBINATOR_LEFT);
}
// wint (count_list_size (c->left));
write_tree (c->left, 0, &T, &x);
}
} else {
if (schema_version >= 1) {
wint (TLS_COMBINATOR_LEFT);
wint (0);
} else {
wint (-11);
}
}
if (schema_version >= 1) {
wint (schema_version >= 2 ? TLS_COMBINATOR_RIGHT_V2 : TLS_COMBINATOR_RIGHT);
}
write_tree (c->right, 1, &T, &x);
}
void write_constructor (struct tl_constructor *c) {
wint (schema_version >= 1 ? TLS_COMBINATOR : 2);
write_combinator (c);
}
void write_function (struct tl_constructor *c) {
wint (schema_version >= 1 ? TLS_COMBINATOR : 3);
write_combinator (c);
}
void write_type_constructors (struct tl_type *t) {
int i;
for (i = 0; i < t->constructors_num; i++) {
write_constructor (t->constructors[i]);
}
}
int MAGIC = 0x850230aa;
void write_types (int f) {
__f = f;
if (schema_version == 1) {
wint (TLS_SCHEMA);
} else if (schema_version == 2) {
wint (TLS_SCHEMA_V2);
} else {
wint (MAGIC);
}
if (schema_version >= 1) {
wint (0);
wint (time (0));
}
num = 0;
if (schema_version >= 1) {
wint (total_types_num);
}
tree_act_tl_type (tl_type_tree, write_type);
if (schema_version >= 1) {
wint (total_constructors_num);
}
tree_act_tl_type (tl_type_tree, write_type_constructors);
if (schema_version >= 1) {
wint (total_functions_num);
}
tree_act_tl_constructor (tl_function_tree, write_function);
}
/*
This file is part of VK/KittenPHP-DB-Engine.
VK/KittenPHP-DB-Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK/KittenPHP-DB-Engine. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#ifndef __TL_PARSER_NEW_H__
#define __TL_PARSER_NEW_H__
enum lex_type {
lex_error,
lex_char,
lex_triple_minus,
lex_uc_ident,
lex_lc_ident,
lex_eof,
lex_final,
lex_new,
lex_none,
lex_num,
lex_empty
};
struct curlex {
char *ptr;
int len;
enum lex_type type;
int flags;
};
struct parse {
char *text;
int pos;
int len;
int line;
int line_pos;
struct curlex lex;
};
enum tree_type {
type_tl_program,
type_fun_declarations,
type_constr_declarations,
type_declaration,
type_combinator_decl,
type_equals,
type_partial_app_decl,
type_final_decl,
type_full_combinator_id,
type_opt_args,
type_args,
type_args1,
type_args2,
type_args3,
type_args4,
type_boxed_type_ident,
type_subexpr,
type_partial_comb_app_decl,
type_partial_type_app_decl,
type_final_new,
type_final_final,
type_final_empty,
// type_type,
type_var_ident,
type_var_ident_opt,
type_multiplicity,
type_type_term,
type_term,
type_percent,
type_result_type,
type_expr,
type_nat_term,
type_combinator_id,
type_nat_const,
type_type_ident,
type_builtin_combinator_decl,
type_exclam,
type_optional_arg_def
};
struct tree {
char *text;
int len;
enum tree_type type;
int lex_line;
int lex_line_pos;
int flags;
int size;
int nc;
struct tree **c;
};
#define TL_ACT(x) (x == act_var ? "act_var" : x == act_field ? "act_field" : x == act_plus ? "act_plus" : x == act_type ? "act_type" : x == act_nat_const ? "act_nat_const" : x == act_array ? "act_array" : x == act_question_mark ? "act_question_mark" : \
x == act_union ? "act_union" : x == act_arg ? "act_arg" : x == act_opt_field ? "act_opt_field" : "act_unknown")
#define TL_TYPE(x) (x == type_num ? "type_num" : x == type_type ? "type_type" : x == type_list_item ? "type_list_item" : x == type_list ? "type_list" : x == type_num_value ? "type_num_value" : "type_unknown")
enum combinator_tree_action {
act_var,
act_field,
act_plus,
act_type,
act_nat_const,
act_array,
act_question_mark,
act_union,
act_arg,
act_opt_field
};
enum combinator_tree_type {
type_num,
type_num_value,
type_type,
type_list_item,
type_list
};
struct tl_combinator_tree {
enum combinator_tree_action act;
struct tl_combinator_tree *left, *right;
char *name;
void *data;
long long flags;
enum combinator_tree_type type;
int type_len;
long long type_flags;
};
struct tl_program {
int types_num;
int functions_num;
int constructors_num;
struct tl_type **types;
struct tl_function **functions;
// struct tl_constuctor **constructors;
};
struct tl_type {
char *id;
char *print_id;
char *real_id;
unsigned name;
int flags;
int params_num;
long long params_types;
int constructors_num;
struct tl_constructor **constructors;
};
struct tl_constructor {
char *id;
char *print_id;
char *real_id;
unsigned name;
struct tl_type *type;
struct tl_combinator_tree *left;
struct tl_combinator_tree *right;
};
struct tl_var {
char *id;
struct tl_combinator_tree *ptr;
int type;
int flags;
};
struct parse *tl_init_parse_file (const char *fname);
struct tree *tl_parse_lex (struct parse *P);
void tl_print_parse_error (void);
struct tl_program *tl_parse (struct tree *T);
void write_types (int f);
#define FLAG_BARE 1
#define FLAG_OPT_VAR (1 << 17)
#define FLAG_EXCL (1 << 18)
#define FLAG_OPT_FIELD (1 << 20)
#define FLAG_IS_VAR (1 << 21)
#define FLAG_DEFAULT_CONSTRUCTOR (1 << 25)
#define FLAG_EMPTY (1 << 10)
#endif
/*
This file is part of VK/KittenPHP-DB-Engine.
VK/KittenPHP-DB-Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK/KittenPHP-DB-Engine. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#ifndef __TL_TL_H__
#define __TL_TL_H__
#define TLS_SCHEMA 0xf19d9e38
#define TLS_TYPE 0x12eb4386
#define TLS_COMBINATOR 0x5c0a1ed5
#define TLS_COMBINATOR_LEFT_BUILTIN 0xcd211f63
#define TLS_COMBINATOR_LEFT 0x4c12c6d9
#define TLS_COMBINATOR_RIGHT 0xd325b367
#define TLS_ARG 0x46afe232
#define TLS_TREE_NAT_CONST 0xc09f07d7
#define TLS_TREE_NAT_VAR 0x90ea6f58
#define TLS_TREE_TYPE_VAR 0x1caa237a
#define TLS_TREE_ARRAY 0x80479360
#define TLS_TREE_TYPE 0x10f32190
#define TLS_SCHEMA_V2 0x3a2f9be2
#define TLS_COMBINATOR_RIGHT_V2 0x2c064372
#define TLS_ARG_V2 0x29dfe61b
#define TLS_EXPR_TYPE 0xecc9da78
#define TLS_EXPR_NAT 0xdcb49bd8
#define TLS_NAT_CONST 0xdcb49bd8
#define TLS_NAT_VAR 0x4e8a14f0
#define TLS_TYPE_VAR 0x0142ceae
#define TLS_ARRAY 0xd9fb20de
#define TLS_TYPE_EXPR 0xc1863d08
#endif
/*
This file is part of VK/KittenPHP-DB-Engine.
VK/KittenPHP-DB-Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK/KittenPHP-DB-Engine. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "tl-parser.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include "config.h"
#include <execinfo.h>
int verbosity;
int output_expressions;
int schema_version = 2;
void usage (void) {
printf ("usage: tlc [-v] [-h] <TL-schema-file>\n"
"\tTL compiler\n"
"\t-v\toutput statistical and debug information into stderr\n"
"\t-E\twhenever is possible output to stdout expressions\n"
"\t-e <file>\texport serialized schema to file\n"
"\t-w\t custom version of serialized schema (0 - very old, 1 - old, 2 - current (default))\n"
);
exit (2);
}
int vkext_write (const char *filename) {
int f = open (filename, O_CREAT | O_WRONLY | O_TRUNC, 0640);
assert (f >= 0);
write_types (f);
close (f);
return 0;
}
void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void logprintf (const char *format __attribute__ ((unused)), ...) {
}
void hexdump (int *in_ptr, int *in_end) {
int *ptr = in_ptr;
while (ptr < in_end) { printf (" %08x", *(ptr ++)); }
printf ("\n");
}
#ifdef HAVE_EXECINFO_H
void print_backtrace (void) {
void *buffer[255];
const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *));
backtrace_symbols_fd (buffer, calls, 1);
}
#else
void print_backtrace (void) {
if (write (1, "No libexec. Backtrace disabled\n", 32) < 0) {
// Sad thing
}
}
#endif
void sig_segv_handler (int signum __attribute__ ((unused))) {
if (write (1, "SIGSEGV received\n", 18) < 0) {
// Sad thing
}
print_backtrace ();
exit (EXIT_FAILURE);
}
void sig_abrt_handler (int signum __attribute__ ((unused))) {
if (write (1, "SIGABRT received\n", 18) < 0) {
// Sad thing
}
print_backtrace ();
exit (EXIT_FAILURE);
}
int main (int argc, char **argv) {
signal (SIGSEGV, sig_segv_handler);
signal (SIGABRT, sig_abrt_handler);
int i;
char *vkext_file = 0;
while ((i = getopt (argc, argv, "Ehve:w:")) != -1) {
switch (i) {
case 'E':
output_expressions++;
break;
case 'h':
usage ();
return 2;
case 'e':
vkext_file = optarg;
break;
case 'w':
schema_version = atoi (optarg);
break;
case 'v':
verbosity++;
break;
}
}
if (argc != optind + 1) {
usage ();
}
struct parse *P = tl_init_parse_file (argv[optind]);
if (!P) {
return 0;
}
struct tree *T;
if (!(T = tl_parse_lex (P))) {
fprintf (stderr, "Error in parse:\n");
tl_print_parse_error ();
return 0;
} else {
if (verbosity) {
fprintf (stderr, "Parse ok\n");
}
if (!tl_parse (T)) {
if (verbosity) {
fprintf (stderr, "Fail\n");
}
return 1;
} else {
if (verbosity) {
fprintf (stderr, "Ok\n");
}
}
}
if (vkext_file) {
vkext_write (vkext_file);
}
return 0;
}
......@@ -151,6 +151,13 @@ void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
tree_check_ ## X_NAME (T->left); \
tree_check_ ## X_NAME (T->right); \
}\
struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return 0; }\
tree_clear_ ## X_NAME (T->left); \
tree_clear_ ## X_NAME (T->right); \
delete_tree_node_ ## X_NAME (T); \
return 0; \
} \
#define int_cmp(a,b) ((a) - (b))
#pragma pack(pop)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment