504 lines
17 KiB
C
504 lines
17 KiB
C
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
// See LICENSE.md for license information.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
// inputHost.c - Host-cc harness for the typed-character queue
|
|
// (jlInputGetChar / jlInputCharPush in src/core/input.c). Exercises
|
|
// FIFO ordering, the character filter, drop-newest overflow, reset
|
|
// semantics, and the jlInputPoll refill path via a mocked
|
|
// jlpInputPoll; a one-button stick's tap (button 0) and hold
|
|
// (button 1), with a mocked jlMillisElapsed; the dead zone, axis scaling
|
|
// and chord rule every port shares (inputDeadZone, inputAxisScale,
|
|
// inputCharTyped); a key two physical keys give, down while either is
|
|
// held (inputKeyHeld); the mouse every port starts in the middle of the
|
|
// stage and keeps on it (inputReset, inputMouseMove); and what ends
|
|
// jlWaitForAnyKey, through a scripted jlpInputPoll.
|
|
//
|
|
// Built by scripts/check-input.sh with -DJOEYLIB_PLATFORM_BLANK so
|
|
// port.h routes jlpInputPoll/jlpJoystickReset to the mocks below.
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "joey/core.h"
|
|
#include "joey/input.h"
|
|
#include "inputInternal.h"
|
|
#include "port.h"
|
|
|
|
// Characters the mocked jlpInputPoll delivers on its next call
|
|
// (one-shot; cleared after delivery).
|
|
static const uint8_t *gMockChars = NULL;
|
|
static int gMockCount = 0;
|
|
|
|
// What the mocked jlpInputPoll reports for stick 0's buttons, and the
|
|
// mocked clock.
|
|
static uint8_t gMockButtons[JL_JOY_BUTTON_COUNT];
|
|
static uint32_t gMockMillis = 0;
|
|
|
|
// A script for jlWaitForAnyKey: each poll applies its next step, the keys
|
|
// held and the characters typed. Past its end the poll holds ESCAPE, which
|
|
// ends any wait, and says so in gWaitOverrun.
|
|
typedef struct {
|
|
uint8_t key; // a jlKeyE held this step, or JL_KEY_NONE
|
|
uint8_t key2; // another, or JL_KEY_NONE
|
|
const char *chars; // typed this step
|
|
} WaitStepT;
|
|
|
|
// One of a key's two physical keys going down or up, and whether the key
|
|
// must then be down.
|
|
typedef struct {
|
|
uint8_t key; // the key, with INPUT_KEY_SECOND for its second
|
|
bool down;
|
|
bool held;
|
|
} KeyStepT;
|
|
|
|
static const WaitStepT *gWaitScript = NULL;
|
|
static int gWaitSteps = 0;
|
|
static int gWaitAt = 0;
|
|
static bool gWaitOverrun = false;
|
|
|
|
// Prototypes (harness-local, alphabetical).
|
|
static bool checkEmpty(const char *name);
|
|
static bool pollJoy(const char *name, uint32_t millis, bool fire, bool down0, bool down1);
|
|
static bool popExpect(const char *name, const uint8_t *expect, int count);
|
|
static void pushAll(const uint8_t *chars, int count);
|
|
static bool runAxisScale(void);
|
|
static bool runChord(void);
|
|
static bool runDeadZone(void);
|
|
static bool runFilter(void);
|
|
static bool runInterleave(void);
|
|
static bool runMouse(void);
|
|
static bool runOrder(void);
|
|
static bool runOverflow(void);
|
|
static bool runPollRefill(void);
|
|
static bool runReset(void);
|
|
static bool runSecondKey(void);
|
|
static bool runTapOrHold(void);
|
|
static bool runWait(void);
|
|
static bool waitEndsAt(const char *name, const WaitStepT *script, int steps, int expect);
|
|
|
|
|
|
void jlpInputPoll(void) {
|
|
const char *c;
|
|
int i;
|
|
|
|
if (gWaitScript != NULL) {
|
|
memset(gKeyState, 0, sizeof(gKeyState));
|
|
if (gWaitAt < gWaitSteps) {
|
|
gKeyState[gWaitScript[gWaitAt].key] = 1u;
|
|
gKeyState[gWaitScript[gWaitAt].key2] = 1u;
|
|
for (c = gWaitScript[gWaitAt].chars; *c != '\0'; c++) {
|
|
jlInputCharPush((uint8_t)*c);
|
|
}
|
|
gWaitAt++;
|
|
} else {
|
|
gKeyState[JL_KEY_ESCAPE] = 1u;
|
|
gWaitOverrun = true;
|
|
}
|
|
gKeyState[JL_KEY_NONE] = 0u;
|
|
return;
|
|
}
|
|
for (i = 0; i < gMockCount; i++) {
|
|
jlInputCharPush(gMockChars[i]);
|
|
}
|
|
gMockCount = 0;
|
|
gJoyButtonState[JL_JOYSTICK_0][JL_JOY_BUTTON_0] = gMockButtons[JL_JOY_BUTTON_0];
|
|
gJoyButtonState[JL_JOYSTICK_0][JL_JOY_BUTTON_1] = gMockButtons[JL_JOY_BUTTON_1];
|
|
}
|
|
|
|
|
|
uint32_t jlMillisElapsed(void) {
|
|
return gMockMillis;
|
|
}
|
|
|
|
|
|
void jlpJoystickReset(jlJoystickE js) {
|
|
(void)js;
|
|
}
|
|
|
|
|
|
static bool checkEmpty(const char *name) {
|
|
int got;
|
|
|
|
got = jlInputGetChar();
|
|
if (got != -1) {
|
|
printf(" %s: expected empty (-1), got %d\n", name, got);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// One poll at `millis` with stick 0's (first) button `fire`; true when
|
|
// buttons 0 and 1 then read down0 and down1.
|
|
static bool pollJoy(const char *name, uint32_t millis, bool fire, bool down0, bool down1) {
|
|
bool got0;
|
|
bool got1;
|
|
|
|
gMockMillis = millis;
|
|
gMockButtons[JL_JOY_BUTTON_0] = fire;
|
|
jlInputPoll();
|
|
got0 = jlJoyDown(JL_JOYSTICK_0, JL_JOY_BUTTON_0);
|
|
got1 = jlJoyDown(JL_JOYSTICK_0, JL_JOY_BUTTON_1);
|
|
if (got0 != down0 || got1 != down1) {
|
|
printf(" %s: at %u ms, fire %d: buttons %d %d, want %d %d\n", name, (unsigned)millis, fire, got0, got1, down0, down1);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool popExpect(const char *name, const uint8_t *expect, int count) {
|
|
int got;
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
got = jlInputGetChar();
|
|
if (got != (int)expect[i]) {
|
|
printf(" %s: index %d: expected 0x%02X, got %d\n", name, i, expect[i], got);
|
|
return false;
|
|
}
|
|
}
|
|
return checkEmpty(name);
|
|
}
|
|
|
|
|
|
static void pushAll(const uint8_t *chars, int count) {
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
jlInputCharPush(chars[i]);
|
|
}
|
|
}
|
|
|
|
|
|
// A raw axis reads -127..127 rounded to the nearest: the ends at the ends,
|
|
// and a centred stick 0 from either middle value of an even span (DVX's
|
|
// -32768..32767 read -1 at rest before it was rounded).
|
|
static bool runAxisScale(void) {
|
|
static const int32_t kPos[] = { INT16_MIN, INT16_MAX, 0, -1, 32767, 32768, 0, 65535, -100 };
|
|
static const int32_t kMin[] = { INT16_MIN, INT16_MIN, INT16_MIN, INT16_MIN, 0, 0, 0, 0, 0 };
|
|
static const int32_t kMax[] = { INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX, 65535, 65535, 65535, 65535, 65535 };
|
|
static const int8_t kOut[] = { -127, 127, 0, 0, 0, 0, -127, 127, -127 };
|
|
uint16_t i;
|
|
bool ok;
|
|
|
|
ok = true;
|
|
for (i = 0u; i < (uint16_t)(sizeof(kPos) / sizeof(kPos[0])); i++) {
|
|
if (inputAxisScale(kPos[i], kMin[i], kMax[i]) != kOut[i]) {
|
|
printf(" axis-scale: %ld in %ld..%ld gave %d, want %d\n", (long)kPos[i], (long)kMin[i], (long)kMax[i], inputAxisScale(kPos[i], kMin[i], kMax[i]), kOut[i]);
|
|
ok = false;
|
|
}
|
|
}
|
|
printf(" axis-scale: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// A chord types nothing, printable or not; the same characters typed
|
|
// plainly arrive.
|
|
static bool runChord(void) {
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
inputCharTyped('m', true);
|
|
inputCharTyped(JL_CHAR_RETURN, true);
|
|
inputCharTyped(JL_CHAR_DELETE, true);
|
|
ok = jlInputGetChar() == -1;
|
|
inputCharTyped('m', false);
|
|
inputCharTyped(JL_CHAR_RETURN, false);
|
|
ok = ok && jlInputGetChar() == 'm' && jlInputGetChar() == JL_CHAR_RETURN && jlInputGetChar() == -1;
|
|
printf(" chord: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// A reading within the dead zone of centre is 0, at its edge too; one past
|
|
// it is the reading; a zone of 0 leaves every reading but 0 alone.
|
|
static bool runDeadZone(void) {
|
|
static const int8_t kIn[] = { 10, 11, -10, -11, 0, 1, -1, 127, -127 };
|
|
static const uint8_t kZone[] = { 10, 10, 10, 10, 0, 0, 0, 10, 10 };
|
|
static const int8_t kOut[] = { 0, 11, 0, -11, 0, 1, -1, 127, -127 };
|
|
uint16_t i;
|
|
bool ok;
|
|
|
|
ok = true;
|
|
for (i = 0u; i < (uint16_t)(sizeof(kIn) / sizeof(kIn[0])); i++) {
|
|
if (inputDeadZone(kIn[i], kZone[i]) != kOut[i]) {
|
|
printf(" dead-zone: %d in a zone of %u gave %d, want %d\n", kIn[i], kZone[i], inputDeadZone(kIn[i], kZone[i]), kOut[i]);
|
|
ok = false;
|
|
}
|
|
}
|
|
printf(" dead-zone: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// Control characters other than BS/TAB/CR/ESC, and 8-bit values, must
|
|
// never surface; those four, the printable range and JL_CHAR_DELETE
|
|
// (0x7F, forward delete) must pass through unchanged.
|
|
static bool runFilter(void) {
|
|
static const uint8_t rejected[] = { 0x00, 0x01, 0x07, 0x0A, 0x0C, 0x1F, 0x80, 0xA0, 0xFF };
|
|
static const uint8_t accepted[] = {
|
|
JL_CHAR_BACKSPACE, JL_CHAR_TAB, JL_CHAR_RETURN, JL_CHAR_ESCAPE,
|
|
0x20, '0', 'Z', 'z', '~', 0x7E, JL_CHAR_DELETE
|
|
};
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
pushAll(rejected, (int)sizeof(rejected));
|
|
ok = checkEmpty("filter-rejects");
|
|
pushAll(accepted, (int)sizeof(accepted));
|
|
ok &= popExpect("filter-accepts", accepted, (int)sizeof(accepted));
|
|
printf(" filter: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// Pops interleaved with pushes keep FIFO order across the wrap point.
|
|
static bool runInterleave(void) {
|
|
static const uint8_t first[] = { 'a', 'b', 'c' };
|
|
static const uint8_t second[] = { 'd', 'e' };
|
|
static const uint8_t rest[] = { 'b', 'c', 'd', 'e' };
|
|
bool ok;
|
|
int got;
|
|
|
|
jlInputCharReset();
|
|
pushAll(first, (int)sizeof(first));
|
|
got = jlInputGetChar();
|
|
ok = (got == 'a');
|
|
if (!ok) {
|
|
printf(" interleave: expected 'a', got %d\n", got);
|
|
}
|
|
pushAll(second, (int)sizeof(second));
|
|
ok &= popExpect("interleave", rest, (int)sizeof(rest));
|
|
printf(" interleave: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// The definition-of-done string from the RetroNet handoff must come
|
|
// back byte-for-byte.
|
|
// jlInit's reset puts the mouse in the middle of the stage; a port's moves
|
|
// stay on it.
|
|
static bool runMouse(void) {
|
|
bool ok;
|
|
|
|
inputMouseMove(5, 7);
|
|
inputReset();
|
|
ok = jlMouseX() == JL_SURFACE_WIDTH / 2 && jlMouseY() == JL_SURFACE_HEIGHT / 2;
|
|
inputMouseMove(-5, 250);
|
|
ok = ok && jlMouseX() == 0 && jlMouseY() == JL_SURFACE_HEIGHT - 1;
|
|
inputMouseMove(400, -1);
|
|
ok = ok && jlMouseX() == JL_SURFACE_WIDTH - 1 && jlMouseY() == 0;
|
|
inputMouseMove(100, 50);
|
|
ok = ok && jlMouseX() == 100 && jlMouseY() == 50;
|
|
printf(" mouse: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
static bool runOrder(void) {
|
|
static const char target[] = "192.168.1.10:6510";
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
pushAll((const uint8_t *)target, (int)(sizeof(target) - 1));
|
|
ok = popExpect("order", (const uint8_t *)target, (int)(sizeof(target) - 1));
|
|
printf(" order: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// Overflow drops the NEWEST characters: exactly JL_CHAR_QUEUE_SIZE - 1
|
|
// survive, and they are the first ones pushed.
|
|
static bool runOverflow(void) {
|
|
uint8_t burst[JL_CHAR_QUEUE_SIZE + 8];
|
|
bool ok;
|
|
int i;
|
|
|
|
jlInputCharReset();
|
|
for (i = 0; i < (int)sizeof(burst); i++) {
|
|
burst[i] = (uint8_t)('!' + (i % 0x5E));
|
|
}
|
|
pushAll(burst, (int)sizeof(burst));
|
|
ok = popExpect("overflow", burst, JL_CHAR_QUEUE_SIZE - 1);
|
|
printf(" overflow: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// The real app-facing path: jlInputPoll runs the port poll, which
|
|
// pushes translated characters; jlInputGetChar then pops them.
|
|
static bool runPollRefill(void) {
|
|
static const uint8_t typed[] = { 'H', 'i', '!', JL_CHAR_RETURN };
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
gMockChars = typed;
|
|
gMockCount = (int)sizeof(typed);
|
|
jlInputPoll();
|
|
ok = popExpect("poll-refill", typed, (int)sizeof(typed));
|
|
jlInputPoll();
|
|
ok &= checkEmpty("poll-refill-once");
|
|
printf(" poll-refill: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// jlInputCharReset empties the queue (the jlInit path).
|
|
static bool runReset(void) {
|
|
static const uint8_t some[] = { 'x', 'y', 'z' };
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
pushAll(some, (int)sizeof(some));
|
|
jlInputCharReset();
|
|
ok = checkEmpty("reset");
|
|
printf(" reset: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// A one-button stick: a press let go within half a second is button 0,
|
|
// down for the one poll after it is let go; a longer press is button 1
|
|
// from half a second until it is let go, with no button 0 after it. A
|
|
// two-button stick's buttons pass through as they are.
|
|
// A key two physical keys give is down while either is held, whichever goes
|
|
// up first; a repeated press or a stray release of one changes nothing.
|
|
static bool runSecondKey(void) {
|
|
static const KeyStepT kSteps[] = {
|
|
{ JL_KEY_UP, true, true },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, true, true },
|
|
{ JL_KEY_UP, false, true },
|
|
{ JL_KEY_UP, true, true },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, false, true },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, false, true },
|
|
{ JL_KEY_UP, false, false },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, true, true },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, true, true },
|
|
{ JL_KEY_UP | INPUT_KEY_SECOND, false, false },
|
|
};
|
|
uint16_t i;
|
|
uint8_t held;
|
|
bool ok;
|
|
|
|
ok = true;
|
|
held = 0u;
|
|
for (i = 0u; i < (uint16_t)(sizeof(kSteps) / sizeof(kSteps[0])); i++) {
|
|
held = inputKeyHeld(held, kSteps[i].key, kSteps[i].down);
|
|
if ((held != 0u) != kSteps[i].held) {
|
|
printf(" second-key: step %u left the key %s\n", i, held != 0u ? "down" : "up");
|
|
ok = false;
|
|
}
|
|
}
|
|
printf(" second-key: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
static bool runTapOrHold(void) {
|
|
bool ok = true;
|
|
|
|
gJoyOneButton[JL_JOYSTICK_0] = true;
|
|
ok &= pollJoy("tap down", 1000u, true, false, false);
|
|
ok &= pollJoy("tap held", 1300u, true, false, false);
|
|
ok &= pollJoy("tap let go", 1350u, false, true, false);
|
|
ok &= jlJoyPressed(JL_JOYSTICK_0, JL_JOY_BUTTON_0);
|
|
ok &= pollJoy("tap over", 1370u, false, false, false);
|
|
ok &= jlJoyReleased(JL_JOYSTICK_0, JL_JOY_BUTTON_0);
|
|
ok &= pollJoy("hold down", 2000u, true, false, false);
|
|
ok &= pollJoy("hold at 499 ms", 2499u, true, false, false);
|
|
ok &= pollJoy("hold at 500 ms", 2500u, true, false, true);
|
|
ok &= jlJoyPressed(JL_JOYSTICK_0, JL_JOY_BUTTON_1);
|
|
ok &= pollJoy("hold on", 2900u, true, false, true);
|
|
ok &= pollJoy("hold let go", 2950u, false, false, false);
|
|
ok &= jlJoyReleased(JL_JOYSTICK_0, JL_JOY_BUTTON_1);
|
|
ok &= pollJoy("hold over", 2970u, false, false, false);
|
|
|
|
gJoyOneButton[JL_JOYSTICK_0] = false;
|
|
gMockButtons[JL_JOY_BUTTON_1] = true;
|
|
ok &= pollJoy("two buttons", 3000u, true, true, true);
|
|
gMockButtons[JL_JOY_BUTTON_1] = false;
|
|
ok &= pollJoy("two buttons up", 3020u, false, false, false);
|
|
printf(" tap-or-hold: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok;
|
|
}
|
|
|
|
|
|
// What ends jlWaitForAnyKey: a named key pressed, or a character typed, but
|
|
// not a key held from the start, nor a held key's own auto-repeat.
|
|
static bool runWait(void) {
|
|
static const WaitStepT kPunctuation[] = {
|
|
{ JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_NONE, JL_KEY_NONE, "," }
|
|
};
|
|
static const WaitStepT kRepeat[] = {
|
|
{ JL_KEY_SPACE, JL_KEY_NONE, "" }, { JL_KEY_SPACE, JL_KEY_NONE, " " }, { JL_KEY_SPACE, JL_KEY_NONE, " " },
|
|
{ JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_NONE, JL_KEY_NONE, "." }
|
|
};
|
|
static const WaitStepT kShifted[] = {
|
|
{ JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_LSHIFT, JL_KEY_NONE, "<" }
|
|
};
|
|
static const WaitStepT kNamed[] = {
|
|
{ JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_A, JL_KEY_NONE, "a" }
|
|
};
|
|
static const WaitStepT kHeld[] = {
|
|
{ JL_KEY_A, JL_KEY_NONE, "" }, { JL_KEY_A, JL_KEY_NONE, "a" }, { JL_KEY_A, JL_KEY_NONE, "a" },
|
|
{ JL_KEY_NONE, JL_KEY_NONE, "" }, { JL_KEY_A, JL_KEY_NONE, "a" }
|
|
};
|
|
bool ok = true;
|
|
|
|
ok &= waitEndsAt("wait: a punctuation key", kPunctuation, 3, 3);
|
|
ok &= waitEndsAt("wait: a held key's repeat", kRepeat, 5, 5);
|
|
ok &= waitEndsAt("wait: shifted punctuation", kShifted, 2, 2);
|
|
ok &= waitEndsAt("wait: a named key", kNamed, 3, 3);
|
|
ok &= waitEndsAt("wait: a key held from the start", kHeld, 5, 5);
|
|
return ok;
|
|
}
|
|
|
|
|
|
// Run jlWaitForAnyKey on script: it should return on poll expect (the
|
|
// first poll is 1), and the character queue be empty.
|
|
static bool waitEndsAt(const char *name, const WaitStepT *script, int steps, int expect) {
|
|
bool ok;
|
|
|
|
jlInputCharReset();
|
|
memset(gKeyState, 0, sizeof(gKeyState));
|
|
gWaitScript = script;
|
|
gWaitSteps = steps;
|
|
gWaitAt = 0;
|
|
gWaitOverrun = false;
|
|
jlWaitForAnyKey();
|
|
gWaitScript = NULL;
|
|
ok = !gWaitOverrun && gWaitAt == expect && jlInputGetChar() == -1;
|
|
printf(" %-34s %s (ended on poll %d%s, %d expected)\n", name, ok ? "PASS" : "FAIL", gWaitAt, gWaitOverrun ? ", past the script" : "", expect);
|
|
return ok;
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
bool ok = true;
|
|
|
|
printf("inputHost: typed-character queue, joystick, and mouse scenarios\n");
|
|
ok &= runOrder();
|
|
ok &= runFilter();
|
|
ok &= runOverflow();
|
|
ok &= runInterleave();
|
|
ok &= runReset();
|
|
ok &= runPollRefill();
|
|
ok &= runTapOrHold();
|
|
ok &= runDeadZone();
|
|
ok &= runAxisScale();
|
|
ok &= runChord();
|
|
ok &= runSecondKey();
|
|
ok &= runMouse();
|
|
ok &= runWait();
|
|
if (!ok) {
|
|
printf("inputHost: FAIL\n");
|
|
return 1;
|
|
}
|
|
printf("inputHost: PASS\n");
|
|
return 0;
|
|
}
|