Fun 0.41.5
The programming language that makes You have fun
Loading...
Searching...
No Matches
input_line.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2025 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
51
53 /* operand bit flags:
54 * bit0 (1): has prompt (string or any value convertible to string) — top of stack holds prompt when set
55 * bit1 (2): hidden input (do not echo typed characters)
56 */
57 int has_prompt = (inst.operand & 1) ? 1 : 0;
58 int hidden = (inst.operand & 2) ? 1 : 0;
59 if (has_prompt) {
60 /* pop prompt value and print without newline */
61 Value pv = pop_value(vm);
62 char *pstr = value_to_string_alloc(&pv);
63 if (pstr) {
64 fputs(pstr, stdout);
65 fflush(stdout);
66 free(pstr);
67 }
68 free_value(pv);
69 }
70
71 /* For hidden input, temporarily disable terminal echo if possible */
72 int echo_disabled = 0;
73#ifdef _WIN32
74 if (hidden) {
75 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
76 if (hStdin != INVALID_HANDLE_VALUE) {
77 DWORD mode;
78 if (GetConsoleMode(hStdin, &mode)) {
79 DWORD newMode = mode & ~(ENABLE_ECHO_INPUT);
80 if (SetConsoleMode(hStdin, newMode)) {
82 }
83 }
84 }
85 }
86#else
87 if (hidden) {
88 /* POSIX termios */
89 struct termios oldt;
90 if (tcgetattr(STDIN_FILENO, &oldt) == 0) {
91 struct termios newt = oldt;
92 newt.c_lflag &= ~(ECHO);
93 if (tcsetattr(STDIN_FILENO, TCSANOW, &newt) == 0) {
95 }
96 }
97 }
98#endif
99
100 /* read a line from stdin, dynamically grow buffer */
101 size_t cap = 128;
102 size_t len = 0;
103 char *buf = (char *)malloc(cap);
104 if (!buf) {
105 fprintf(stderr, "Runtime error: out of memory reading input");
106 push_value(vm, make_string(""));
107 /* On early exit, try to restore echo if we turned it off */
108 goto restore_echo_and_break;
109 }
110
111 int ch;
112 while ((ch = fgetc(stdin)) != EOF) {
113 if (ch == '\r') {
114 /* Handle CRLF by consuming optional following '\n' */
115 int next = fgetc(stdin);
116 if (next != EOF && next != '\n') {
117 ungetc(next, stdin);
118 }
119 break;
120 }
121 if (ch == '\n') {
122 break;
123 }
124 if (len + 1 >= cap) {
125 cap *= 2;
126 char *nb = (char *)realloc(buf, cap);
127 if (!nb) {
128 free(buf);
129 fprintf(stderr, "Runtime error: out of memory reading input");
130 push_value(vm, make_string(""));
131 goto push_done;
132 }
133 buf = nb;
134 }
135 buf[len++] = (char)ch;
136 }
137
138 /* null-terminate */
139 if (len + 1 >= cap) {
140 char *nb = (char *)realloc(buf, len + 1);
141 if (!nb) {
142 free(buf);
143 fprintf(stderr, "Runtime error: out of memory finalizing input");
144 push_value(vm, make_string(""));
145 goto push_done;
146 }
147 buf = nb;
148 }
149 buf[len] = '\0';
150
151 /* push as Fun string */
154
155push_done:
156 /* If we disabled echo, restore terminal settings and print a newline for UX */
157#ifdef _WIN32
158 if (echo_disabled) {
159 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
160 if (hStdin != INVALID_HANDLE_VALUE) {
161 DWORD mode;
162 if (GetConsoleMode(hStdin, &mode)) {
163 /* Re-enable ECHO flag */
164 mode |= ENABLE_ECHO_INPUT;
165 SetConsoleMode(hStdin, mode);
166 }
167 }
168 if (has_prompt) {
169 fputc('\n', stdout);
170 fflush(stdout);
171 }
172 }
173#else
174 if (echo_disabled) {
175 struct termios t;
176 if (tcgetattr(STDIN_FILENO, &t) == 0) {
177 t.c_lflag |= ECHO;
178 tcsetattr(STDIN_FILENO, TCSANOW, &t);
179 }
180 if (has_prompt) {
181 fputc('\n', stdout);
182 fflush(stdout);
183 }
184 }
185#endif
186restore_echo_and_break:
187 break;
188}
@ OP_INPUT_LINE
Definition bytecode.h:141
int ch
Definition input_line.c:111
int echo_disabled
Definition input_line.c:72
size_t len
Definition input_line.c:102
size_t cap
Definition input_line.c:101
int hidden
Definition input_line.c:58
push_value(vm, make_string(buf))
char * buf
Definition input_line.c:103
free(buf)
long t
Definition sleep_ms.c:32
Tagged union representing a Fun value.
Definition value.h:68
Value make_string(const char *s)
Construct a string Value by duplicating the given C string.
Definition value.c:95
void free_value(Value v)
Free dynamic storage owned by a Value.
Definition value.c:517
char * value_to_string_alloc(const Value *v)
Allocate a printable C string for a Value.
Definition value.c:641
#define fprintf
Definition vm.c:200