static void command_terminated(struct wait_id id __attribute__((unused)), void *data, int status, enum command_kill_status killed, size_t out_size, const char *out, size_t err_size, const char *err) { struct lua_command_data *lcd = data; struct lua_State *L = lcd->L; ASSERT(L); // This may be called from C code with a dirty stack luaL_checkstack(L, 6, "Not enough stack space to call command callback"); int handler = push_err_handler(L); if (lcd->postfork_callback) { /* * This already happened in the child. But we need to free * resources ‒ remove it from the registry table. */ extract_registry_value(L, lcd->postfork_callback); lua_pop(L, 1); } // Get the lua function. ASSERT(lcd->terminated_callback); extract_registry_value(L, lcd->terminated_callback); /* * We terminated the command, we won't need it any more. * Make sure we don't leak even if the lua throws or whatever. */ free(lcd); // Push the rest of parameters here lua_pushinteger(L, WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)); const char *ks = NULL; switch (killed) { #define KS(NAME) case CK_##NAME: ks = #NAME; break KS(TERMINATED); KS(TERMED); KS(KILLED); KS(SIGNAL_OTHER); #undef KS } ASSERT(ks); lua_pushstring(L, ks); lua_pushlstring(L, out, out_size); lua_pushlstring(L, err, err_size); int result = lua_pcall(L, 4, 0, handler); ASSERT_MSG(!result, "%s", interpreter_error_result(L)); }
/* * MISTY1 Key Schedule */ void MISTY1::key_schedule(const byte key[], size_t length) { secure_vector<u16bit> KS(32); for(size_t i = 0; i != length / 2; ++i) KS[i] = load_be<u16bit>(key, i); for(size_t i = 0; i != 8; ++i) { KS[i+ 8] = FI(KS[i], KS[(i+1) % 8] >> 9, KS[(i+1) % 8] & 0x1FF); KS[i+16] = KS[i+8] >> 9; KS[i+24] = KS[i+8] & 0x1FF; } /* * Precomputed indexes for the orderings of the subkeys (MISTY1 reuses * values) */ static const byte EK_ORDER[100] = { 0x00, 0x0E, 0x0A, 0x04, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05, 0x01, 0x0F, 0x0B, 0x05, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07, 0x02, 0x08, 0x0C, 0x06, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01, 0x03, 0x09, 0x0D, 0x07, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03, 0x04, 0x0A, 0x0E, 0x00 }; static const byte DK_ORDER[100] = { 0x00, 0x0E, 0x0A, 0x04, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02, 0x07, 0x0D, 0x09, 0x03, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00, 0x06, 0x0C, 0x08, 0x02, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06, 0x05, 0x0B, 0x0F, 0x01, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 0x04, 0x0A, 0x0E, 0x00 }; EK.resize(100); DK.resize(100); for(size_t i = 0; i != 100; ++i) { EK[i] = KS[EK_ORDER[i]]; DK[i] = KS[DK_ORDER[i]]; } }
static PyObject* _arraytok(PyObject* self, PyObject* a) { K kobj = 0; if (!PyArray_Check(a)) { return PyErr_Format(PyExc_TypeError, "argument is not a numeric array"); } PyArrayObject* arr = (PyArrayObject*)a; if (!PyArray_ISCONTIGUOUS(arr)) { return PyErr_Format(PyExc_TypeError, "cannot handle non-contiguous arrays"); } int n = PyArray_SIZE(arr); int t = ktype(arr->descr->type_num); if (t > 0) { kobj = gtn(-t,n); memcpy(kobj->k, arr->data, PyArray_NBYTES(arr)); } else if (arr->descr->type_num == PyArray_OBJECT) { /* special handling for arrays of strings */ char** strings = malloc(n*sizeof(char*)); PyObject** objects = (PyObject**)arr->data; int i; for (i = 0; i < n; ++i) { char* str = PyString_AsString(objects[i]); if (str) { strings[i] = str; } else { free(strings); /* XXX should we raise our own exception here * * XXX or keep the one which came from "AsString"? */ return NULL; } } kobj = gtn(-4, n); for (i = 0; i < n; ++i) { KS(kobj)[i] = sp(strings[i]); } } return PyK_mk_K(kobj); }
void Camellia::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { #define KS(i, j) ks[i*4 + EFI(j/2)*2 + EFI(j%2)] #define FL(klh, kll, krh, krl) \ ll ^= rotlFixed(lh & klh, 1); \ lh ^= (ll | kll); \ rh ^= (rl | krl); \ rl ^= rotlFixed(rh & krh, 1); word32 lh, ll, rh, rl; typedef BlockGetAndPut<word32, BigEndian> Block; Block::Get(inBlock)(lh)(ll)(rh)(rl); const word32 *ks = m_key.data(); lh ^= KS(0,0); ll ^= KS(0,1); rh ^= KS(0,2); rl ^= KS(0,3); // timing attack countermeasure. see comments at top for more details const int cacheLineSize = GetCacheLineSize(); unsigned int i; volatile word32 _u = 0; word32 u = _u; assert(IsAlignedOn(s1,GetAlignmentOf<word32>())); for (i=0; i<256; i+=cacheLineSize) u &= *(const word32 *)(void*)(s1+i); u &= *(const word32 *)(void*)(s1+252); lh |= u; ll |= u; SLOW_ROUND(lh, ll, rh, rl, KS(1,0), KS(1,1)) SLOW_ROUND(rh, rl, lh, ll, KS(1,2), KS(1,3)) for (i = m_rounds-1; i > 0; --i) { DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) DOUBLE_ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1), KS(3,2), KS(3,3)) FL(KS(4,0), KS(4,1), KS(4,2), KS(4,3)); DOUBLE_ROUND(lh, ll, rh, rl, KS(5,0), KS(5,1), KS(5,2), KS(5,3)) ks += 16; } DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3)) ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1)) SLOW_ROUND(rh, rl, lh, ll, KS(3,2), KS(3,3)) lh ^= KS(4,0); ll ^= KS(4,1); rh ^= KS(4,2); rl ^= KS(4,3); Block::Put(xorBlock, outBlock)(rh)(rl)(lh)(ll); }
_iAgent.setupLayers(); _iAgent.computeLoop(); } //\/ CellAutomataAgent /\////////////////////////////////////////////////////// // --- STATIC FIELDS --- // SPtr<KRecordType> CellAutomataAgent::START_T; SPtr<KGridType> CellAutomataAgent::PARTITION_MAP_T; SPtr<KGridType> CellAutomataAgent::CELL_GRID_T; SPtr<KRecordType> CellAutomataAgent::BORDER_T; const SPtr<KString> CellAutomataAgent::OP_START = KS("knorba.demo.cell-automata.start"); const SPtr<KString> CellAutomataAgent::OP_PARTITION = KS("knorba.demo.cell-automata.partition"); const SPtr<KString> CellAutomataAgent::OP_BORDER = KS("knorba.demo.cell-automata.border"); const SPtr<KString> CellAutomataAgent::OP_SET_DELAY = KS("knorba.demo.cell-automata.set-delay"); const SPtr<KString> CellAutomataAgent::R_MATE = KS("mate"); const SPtr<KString> CellAutomataAgent::R_OUTPUT = KS("output"); // --- STATIC METHODS --- //
namespace protocol { // --- STATIC FIELDS --- // const SPtr<KString> GroupingProtocol::OP_HELLO = KS("knorba.grouping.hello"); // --- STATIC METHODS --- // void GroupingProtocol::init(Runtime& rt) { rt.registerMessageFormat(OP_HELLO, KType::LONGINT); } // --- (DE)CONSTRUCTORS --- // GroupingProtocol::GroupingProtocol(Agent* owner, PPtr<KString> role, k_longint_t groupId) : Protocol(owner) { _role = role; _groupId = new KLongint(groupId); registerHandler((phandler_t)&GroupingProtocol::handleOpHello, OP_HELLO); } // --- METHODS --- // void GroupingProtocol::start() { if(_agent->getRuntime().getNodeCount() == 1) { onAllMembersConnected(); } else { _agent->sendToAll(OP_HELLO, _groupId.AS(KValue)); } } k_integer_t GroupingProtocol::getNMembers() const { return _agent->getPeers(_role)->getCount() + 1; } // Virtual Methods // void GroupingProtocol::onMemberConnected(const k_guid_t& guid) { // Nothing; } void GroupingProtocol::onMemberDisconnected(const k_guid_t& guid) { // Nothing; } void GroupingProtocol::onAllMembersConnected() { // Nothing; } // Handlers // void GroupingProtocol::handleOpHello(PPtr<Message> msg) { k_longint_t groupId = msg->getPayload().AS(KLongint)->get(); if(groupId == _groupId->get()) { const k_guid_t& sender = msg->getSender(); if(!_agent->getPeers(_role)->containts(sender)) { _agent->send(sender, OP_HELLO, _groupId.AS(KValue)); _agent->addPeer(_role, msg->getSender()); onMemberConnected(msg->getSender()); if(_agent->getRuntime().getNodeCount() == getNMembers()) { onAllMembersConnected(); } } } } // Inherited from Protocol // void GroupingProtocol::handlePeerDisconnected(PPtr<KString> role, const k_guid_t& guid) { if(role->equals(_role)) { onMemberDisconnected(guid); } } } // namespace protocol
{ // Nothing; } void ChatAgent::PConsole::onInputReceived(PPtr<KString> input) { dynamic_cast<ChatAgent*>(_agent)->processInput(input); } //\/ ChatAgent /\////////////////////////////////////////////////////////////// // --- STATIC FIELDS --- // SPtr<KRecordType> ChatAgent::MESSAGE_T; const SPtr<KString> ChatAgent::OP_MESSAGE = KS("knorba.demo.chat.message"); // --- STATIC METHODS --- // SPtr<KRecordType> ChatAgent::message_t() { if(MESSAGE_T.isNull()) { MESSAGE_T = new KRecordType("knorba.demo.chat.Message"); MESSAGE_T->addField("sender", KType::STRING) ->addField("content", KType::STRING); } return MESSAGE_T; } // --- (DE)CONSTRUCTORS --- //
// Whirlpool basic transformation. Transforms state based on block. void Whirlpool::Transform(word64 *digest, const word64 *block) { word64 w[8]; // temporary storage word64 s[8]; // the cipher state word64 k[8]; // the round key // Compute and apply K^0 to the cipher state // Also apply part of the Miyaguchi-Preneel compression function digest[0] = s[0] = block[0] ^ (k[0] = digest[0]); digest[1] = s[1] = block[1] ^ (k[1] = digest[1]); digest[2] = s[2] = block[2] ^ (k[2] = digest[2]); digest[3] = s[3] = block[3] ^ (k[3] = digest[3]); digest[4] = s[4] = block[4] ^ (k[4] = digest[4]); digest[5] = s[5] = block[5] ^ (k[5] = digest[5]); digest[6] = s[6] = block[6] ^ (k[6] = digest[6]); digest[7] = s[7] = block[7] ^ (k[7] = digest[7]); // Iterate over all rounds: for (int r = 0; r < R; r++) { word64 t; // Compute K^r from K^{r-1}: #define K(i,j) GETBYTE(k[(i+j+1)%8], j) #define KS(i) \ t = C0[K(i,3)] ^ C1[K(i,2)] ^ C2[K(i,1)] ^ C3[K(i,0)]; \ w[i] = (t >> 32) ^ (t << 32) ^ C0[K(i,7)] ^ C1[K(i,6)] ^ C2[K(i,5)] ^ C3[K(i,4)]; KS(0); KS(1); KS(2); KS(3); KS(4); KS(5); KS(6); KS(7); k[0] = w[0] ^ rc[r]; k[1] = w[1]; k[2] = w[2]; k[3] = w[3]; k[4] = w[4]; k[5] = w[5]; k[6] = w[6]; k[7] = w[7]; // Apply the r-th round transformation: #define S(i,j) GETBYTE(s[(i+j+1)%8], j) #define TS(i) \ t = C0[S(i,3)] ^ C1[S(i,2)] ^ C2[S(i,1)] ^ C3[S(i,0)]; \ w[i] = (t >> 32) ^ (t << 32) ^ C0[S(i,7)] ^ C1[S(i,6)] ^ C2[S(i,5)] ^ C3[S(i,4)] ^ k[i]; TS(0); TS(1); TS(2); TS(3); TS(4); TS(5); TS(6); TS(7); s[0] = w[0]; s[1] = w[1]; s[2] = w[2]; s[3] = w[3]; s[4] = w[4]; s[5] = w[5]; s[6] = w[6]; s[7] = w[7]; } // Apply the rest of the Miyaguchi-Preneel compression function: digest[0] ^= s[0]; digest[1] ^= s[1]; digest[2] ^= s[2]; digest[3] ^= s[3]; digest[4] ^= s[4]; digest[5] ^= s[5]; digest[6] ^= s[6]; digest[7] ^= s[7]; }
static PyObject* _ktoarray(PyObject* self, PyObject* k) { PyArrayObject *ret; if (!PyK_KCheck(k)) { return PyErr_Format(PyExc_TypeError, "not k object"); } K kobj = ((PyK_K*)k)->kobj; if (!kobj) { return PyErr_Format(PyExc_AssertionError, "null kobj"); } int t = kobj->t; /* XXX k objects of type 0 should be converted * to non-contiguous arrays rather than trigger * an error. */ if (abs(t) >= LEN(types) && t != 5 ) { return PyErr_Format(PyExc_TypeError, "cannot create an array from a " "k object of type %d", t); } int type = types[abs(t)]; /* PyArray type */ int nd = t <= 0 || t == 5; /* Number of dimensions (0 or 1) */ int* d = &kobj->n; /* Shape */ char* data; switch (t) { case 1: data = (char*)&Ki(kobj); break; case 3: data = &Kc(kobj); break; case 4: data = Ks(kobj); break; default: data = KC(kobj); } /* Special handling for symbols arrays: convert data to Python strings */ PyObject** buf = 0; if (t == -4) { int n = *d, i = 0; buf = (PyObject**)malloc(n * sizeof(PyObject*)); for (i = 0; i < n; ++i) { char* s = KS(kobj)[i]; if (!s) goto fail; buf[i] = PyString_FromString(s); if (!buf[i]) goto fail; } data = (char*)buf; } else if (t == 0 || t == 5) { int n = *d, i = 0; buf = (PyObject**)malloc(n * sizeof(PyObject*)); for (i = 0; i < n; ++i) { K ki = KK(kobj)[i]; if (!ki) goto fail; ci(ki); buf[i] = PyK_mk_K(ki); if (!buf[i]) { cd(ki); goto fail; } } data = (char*)buf; } if (!(ret = (PyArrayObject *)PyArray_FromDimsAndData(nd, d, type, data))) { goto fail; } if (buf) { ret->flags |= OWN_DATA; } else { Py_INCREF(k); ret->base = k; } return (PyObject*)ret; fail: if (buf) free(buf); return NULL; }
/* XXX unfortunately API function gnk of which pyk.gk is based is a vararg function and therefore cannot be portably exported to Python. It would be better if libk20 supplied a function gnk_(I, K*) in addition to gnk(I,...) which would take an array of K objects as the second argument */ static PyObject* _gk(PyObject* self, PyObject* args) { int n = PyTuple_Size(args); if (!n) { return _mk_K(gtn(0,0)); } int i, type = INT_MAX; K* ks = (K*)malloc(n*sizeof(K)); K kobj; for(i = 0; i < n; i++) { K ki; int t; PyObject* argi = PyTuple_GET_ITEM(args, i); if (!IS_K(argi)) { goto fail; } ks[i] = ki = ((_K*)argi)->kobj; t = ki->t; if (INT_MAX == type) { type = t; } else if (t > 4 || t < 1 || t != type) { type = 0; } } kobj = gtn((type>0 && type<5)?-type:0, n); if (!kobj) { free(ks); return PyErr_Format(PyExc_TypeError, "gtn(%d,%d) returned null", -type, n); } switch (type) { case 1: for (i = 0; i < n; i++) { KI(kobj)[i] = Ki(ks[i]); } break; case 2: for (i = 0; i < n; i++) { KF(kobj)[i] = Kf(ks[i]); } break; case 3: for (i = 0; i < n; i++) { KC(kobj)[i] = Kc(ks[i]); } break; case 4: for (i = 0; i < n; i++) { KS(kobj)[i] = Ks(ks[i]); } break; default: memcpy(KK(kobj), ks, n*sizeof(K)); for (i = 0; i < n; i++) { ci(ks[i]); } break; } free(ks); return _mk_K(kobj); fail: free(ks); PyErr_BadArgument(); return NULL; }
int main(void) { struct xkb_context *ctx = test_get_context(0); struct xkb_keymap *keymap; assert(ctx); keymap = test_compile_rules(ctx, "evdev", "evdev", "us,il,ru,de", ",,phonetic,neo", "grp:alt_shift_toggle,grp:menu_toggle"); assert(keymap); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* Simple shifted level. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* Key repeat shifted and unshifted in the middle. */ assert(test_key_seq(keymap, KEY_H, DOWN, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, REPEAT, XKB_KEY_H, NEXT, KEY_H, REPEAT, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, UP, XKB_KEY_h, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Base modifier cleared on key release... */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); /* ... But only by the keycode that set it. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); /* * A base modifier should only be cleared when no other key affecting * the modifier is down. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* * Two key presses from the same key (e.g. if two keyboards use the * same xkb_state) should only be released after two releases. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Same as above with locked modifiers. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Group switching / locking. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_K, BOTH, XKB_KEY_hebrew_lamed, NEXT, KEY_F, BOTH, XKB_KEY_hebrew_kaph, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); assert(test_key_seq(keymap, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH)); assert(test_key_seq(keymap, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)); /* Locked modifiers. */ assert(test_key_seq(keymap, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* * A key release affecting a locked modifier should clear it * regardless of the key press. */ /* assert(test_key_seq(keymap, */ /* KEY_H, BOTH, XKB_KEY_h, NEXT, */ /* KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_E, BOTH, XKB_KEY_E, NEXT, */ /* KEY_L, BOTH, XKB_KEY_L, NEXT, */ /* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_L, BOTH, XKB_KEY_L, NEXT, */ /* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_O, BOTH, XKB_KEY_o, FINISH)); */ /* Simple Num Lock sanity check. */ assert(test_key_seq(keymap, KEY_KP1, BOTH, XKB_KEY_KP_End, NEXT, KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_KP2, BOTH, XKB_KEY_KP_2, NEXT, KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT, KEY_KP2, BOTH, XKB_KEY_KP_Down, FINISH)); /* Test that the aliases in the ru(phonetic) symbols map work. */ assert(test_key_seq(keymap, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_Q, BOTH, XKB_KEY_Cyrillic_ya, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_1, BOTH, XKB_KEY_exclam, NEXT, KEY_Q, BOTH, XKB_KEY_Cyrillic_YA, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, FINISH)); #define KS(name) xkb_keysym_from_name(name, 0) /* Test that levels (1-5) in de(neo) symbols map work. */ assert(test_key_seq(keymap, /* Switch to the group. */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, /* Level 1. */ KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_Q, BOTH, XKB_KEY_x, NEXT, KEY_KP7, BOTH, XKB_KEY_KP_7, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, /* Level 2 with Shift. */ KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_1, BOTH, XKB_KEY_degree, NEXT, KEY_Q, BOTH, XKB_KEY_X, NEXT, KEY_KP7, BOTH, KS("U2714"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, /* * XXX: de(neo) uses shift(both_capslock) which causes * the interesting result in the next line. Since it's * a key release, it doesn't actually lock the modifier, * and applications by-and-large ignore the keysym on * release(?). Is this a problem? */ KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, /* Level 2 with the Lock modifier. */ KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_6, BOTH, XKB_KEY_6, NEXT, KEY_H, BOTH, XKB_KEY_S, NEXT, KEY_KP3, BOTH, XKB_KEY_KP_3, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, /* Level 3. */ KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_6, BOTH, XKB_KEY_cent, NEXT, KEY_Q, BOTH, XKB_KEY_ellipsis, NEXT, KEY_KP7, BOTH, KS("U2195"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Level 4. */ KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_5, BOTH, XKB_KEY_malesymbol, NEXT, KEY_E, BOTH, XKB_KEY_Greek_lambda, NEXT, KEY_SPACE, BOTH, XKB_KEY_nobreakspace, NEXT, KEY_KP8, BOTH, XKB_KEY_intersection, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Level 5. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, /* XXX: xkeyboard-config is borked when de(neo) is * not the first group - not our fault. We test * Level5 seprately below with only de(neo). */ /* KEY_5, BOTH, XKB_KEY_periodcentered, NEXT, */ /* KEY_E, BOTH, XKB_KEY_Up, NEXT, */ /* KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, */ /* KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, */ KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_V, BOTH, XKB_KEY_p, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, "evdev", "", "de", "neo", ""); assert(keymap); assert(test_key_seq(keymap, /* Level 5. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_5, BOTH, XKB_KEY_periodcentered, NEXT, KEY_E, BOTH, XKB_KEY_Up, NEXT, KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, /* Level 6. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_5, BOTH, XKB_KEY_NoSymbol, NEXT, KEY_8, BOTH, XKB_KEY_ISO_Left_Tab, NEXT, KEY_E, BOTH, XKB_KEY_Up, NEXT, KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, /* Level 7. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_5, BOTH, KS("U2221"), NEXT, KEY_E, BOTH, XKB_KEY_Greek_LAMBDA, NEXT, KEY_SPACE, BOTH, KS("U202F"), NEXT, KEY_KP8, BOTH, KS("U22C2"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, /* Level 8. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, /* This doesn't actually lock Level5. Not our fault. */ KEY_TAB, BOTH, XKB_KEY_ISO_Level5_Lock, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_V, BOTH, XKB_KEY_p, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, "evdev", "", "us,il,ru", "", "grp:alt_shift_toggle_bidir,grp:menu_toggle"); assert(keymap); assert(test_key_seq(keymap, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH)); assert(test_key_seq(keymap, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)); /* Check backwards (negative) group switching and wrapping. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, "evdev", "", "us,il,ru", "", "grp:switch,grp:lswitch,grp:menu_toggle"); assert(keymap); /* Test depressed group works (Mode_switch). */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Test locked+depressed group works, with wrapping and accumulation. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, /* Should wrap back to first group. */ KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, /* Two SetGroup(+1)'s should add up. */ KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_file(ctx, "keymaps/unbound-vmod.xkb"); assert(keymap); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_Z, BOTH, XKB_KEY_y, NEXT, KEY_MINUS, BOTH, XKB_KEY_ssharp, NEXT, KEY_Z, BOTH, XKB_KEY_y, FINISH)); xkb_keymap_unref(keymap); xkb_context_unref(ctx); return 0; }