|
14 | 14 | using Microsoft.Scripting.Runtime; |
15 | 15 |
|
16 | 16 | using IronPython.Runtime; |
| 17 | +using IronPython.Runtime.Exceptions; |
17 | 18 | using IronPython.Runtime.Operations; |
| 19 | +using IronPython.Runtime.Types; |
18 | 20 |
|
19 | 21 | using static IronPython.Modules.PythonIOModule; |
20 | 22 |
|
@@ -323,8 +325,81 @@ public static void PerformModuleReload(PythonContext context, PythonDictionary d |
323 | 325 | public static int B230400 => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 230400 : 0x1003; |
324 | 326 | // higher baud rates are not defined on macOS |
325 | 327 |
|
| 328 | + #endregion |
| 329 | + |
| 330 | + |
| 331 | + #region Public Functions |
| 332 | + |
| 333 | + [DllImport("libc", SetLastError = true, EntryPoint = "tcsendbreak")] |
| 334 | + private static extern int _tcsendbreak(int fd, int duration); |
| 335 | + |
| 336 | + [LightThrowing] |
| 337 | + public static object? tcsendbreak(CodeContext context, int fd, int duration) { |
| 338 | + CheckFileDescriptor(fd); |
| 339 | + if (_tcsendbreak(fd, duration) == -1) { |
| 340 | + return LightExceptions.Throw(GetLastTermiosError(context)); |
| 341 | + } |
| 342 | + return null; |
| 343 | + } |
| 344 | + |
| 345 | + [LightThrowing] |
| 346 | + public static object? tcsendbreak(CodeContext context, object? fd, int duration) |
| 347 | + => tcsendbreak(context, PythonFcntl.GetFileDescriptor(context, fd), duration); |
| 348 | + |
| 349 | + |
| 350 | + [DllImport("libc", SetLastError = true, EntryPoint = "tcdrain")] |
| 351 | + private static extern int _tcdrain(int fd); |
| 352 | + |
| 353 | + [LightThrowing] |
| 354 | + public static object? tcdrain(CodeContext context, int fd) { |
| 355 | + CheckFileDescriptor(fd); |
| 356 | + if (_tcdrain(fd) == -1) { |
| 357 | + return LightExceptions.Throw(GetLastTermiosError(context)); |
| 358 | + } |
| 359 | + return null; |
| 360 | + } |
| 361 | + |
| 362 | + [LightThrowing] |
| 363 | + public static object? tcdrain(CodeContext context, object? fd) |
| 364 | + => tcdrain(context, PythonFcntl.GetFileDescriptor(context, fd)); |
| 365 | + |
| 366 | + |
| 367 | + [DllImport("libc", SetLastError = true, EntryPoint = "tcflush")] |
| 368 | + private static extern int _tcflush(int fd, int queue); |
| 369 | + |
| 370 | + [LightThrowing] |
| 371 | + public static object? tcflush(CodeContext context, int fd, int queue) { |
| 372 | + CheckFileDescriptor(fd); |
| 373 | + if (_tcflush(fd, queue) == -1) { |
| 374 | + return LightExceptions.Throw(GetLastTermiosError(context)); |
| 375 | + } |
| 376 | + return null; |
| 377 | + } |
| 378 | + |
| 379 | + [LightThrowing] |
| 380 | + public static object? tcflush(CodeContext context, object? fd, int queue) |
| 381 | + => tcflush(context, PythonFcntl.GetFileDescriptor(context, fd), queue); |
| 382 | + |
| 383 | + |
| 384 | + [DllImport("libc", SetLastError = true, EntryPoint = "tcflow")] |
| 385 | + private static extern int _tcflow(int fd, int action); |
| 386 | + |
| 387 | + [LightThrowing] |
| 388 | + public static object? tcflow(CodeContext context, int fd, int action) { |
| 389 | + CheckFileDescriptor(fd); |
| 390 | + if (_tcflow(fd, action) == -1) { |
| 391 | + return LightExceptions.Throw(GetLastTermiosError(context)); |
| 392 | + } |
| 393 | + return null; |
| 394 | + } |
| 395 | + |
| 396 | + [LightThrowing] |
| 397 | + public static object? tcflow(CodeContext context, object? fd, int action) |
| 398 | + => tcflow(context, PythonFcntl.GetFileDescriptor(context, fd), action); |
| 399 | + |
| 400 | + |
326 | 401 | public static object tcgetattr(CodeContext context, int fd) { |
327 | | - if (fd < 0) throw PythonOps.ValueError("file descriptor cannot be a negative integer ({0})", fd); |
| 402 | + CheckFileDescriptor(fd); |
328 | 403 | if (fd > 0) throw new NotImplementedException("termios support only for stdin"); |
329 | 404 |
|
330 | 405 | if (context.LanguageContext.SystemStandardIn is not TextIOWrapper stdin) { |
@@ -360,6 +435,7 @@ public static object tcgetattr(CodeContext context, object? file) { |
360 | 435 |
|
361 | 436 |
|
362 | 437 | public static void tcsetattr(CodeContext context, int fd, int when, object? attributes) { |
| 438 | + CheckFileDescriptor(fd); |
363 | 439 | if (fd != 0) throw new NotImplementedException(); |
364 | 440 |
|
365 | 441 | if (context.LanguageContext.SystemStandardIn is not TextIOWrapper stdin) { |
@@ -528,11 +604,20 @@ public RawConsole(CodeContext context) : base(context) { |
528 | 604 | public override bool isatty(CodeContext context) => true; |
529 | 605 | } |
530 | 606 |
|
531 | | - private static int ToInt(this object? o) |
532 | | - => o switch { |
533 | | - int i => i, |
534 | | - BigInteger bi => (int)bi, |
535 | | - Extensible<BigInteger> ebi => (int)ebi.Value, |
536 | | - _ => throw PythonOps.TypeErrorForBadInstance("an integer is required (got type {0})", o) |
537 | | - }; |
| 607 | + |
| 608 | + private static void CheckFileDescriptor(int fd) { |
| 609 | + if (fd < 0) { |
| 610 | + throw PythonOps.ValueError("file descriptor cannot be a negative integer ({0})", fd); |
| 611 | + } |
| 612 | + } |
| 613 | + |
| 614 | + |
| 615 | + private static Exception GetLastTermiosError(CodeContext context) { |
| 616 | + int errno = Marshal.GetLastWin32Error(); |
| 617 | + return PythonExceptions.CreateThrowable(termioserror(context), errno, PythonNT.strerror(errno)); |
| 618 | + } |
| 619 | + |
| 620 | + |
| 621 | + private static PythonType termioserror(CodeContext context) |
| 622 | + => (PythonType)context.LanguageContext.GetModuleState("termioserror"); |
538 | 623 | } |
0 commit comments