1 | //===- AutoConvert.cpp - Auto conversion between ASCII/EBCDIC -------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains functions used for auto conversion between |
10 | // ASCII/EBCDIC codepages specific to z/OS. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifdef __MVS__ |
15 | |
16 | #include "llvm/Support/AutoConvert.h" |
17 | #include <cassert> |
18 | #include <fcntl.h> |
19 | #include <sys/stat.h> |
20 | #include <unistd.h> |
21 | |
22 | static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1}; |
23 | |
24 | int disableAutoConversion(int FD) { |
25 | static const struct f_cnvrt Convert = { |
26 | SETCVTOFF, // cvtcmd |
27 | 0, // pccsid |
28 | 0, // fccsid |
29 | }; |
30 | |
31 | return fcntl(FD, F_CONTROL_CVT, &Convert); |
32 | } |
33 | |
34 | int restoreStdHandleAutoConversion(int FD) { |
35 | assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO); |
36 | if (savedStdHandleAutoConversionMode[FD] == -1) |
37 | return 0; |
38 | struct f_cnvrt Cvt = { |
39 | savedStdHandleAutoConversionMode[FD], // cvtcmd |
40 | 0, // pccsid |
41 | 0, // fccsid |
42 | }; |
43 | return (fcntl(FD, F_CONTROL_CVT, &Cvt)); |
44 | } |
45 | |
46 | int enableAutoConversion(int FD) { |
47 | struct f_cnvrt Query = { |
48 | QUERYCVT, // cvtcmd |
49 | 0, // pccsid |
50 | 0, // fccsid |
51 | }; |
52 | |
53 | if (fcntl(FD, F_CONTROL_CVT, &Query) == -1) |
54 | return -1; |
55 | |
56 | // We don't need conversion for UTF-8 tagged files. |
57 | // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve |
58 | // problems related to UTF-8 tagged source files. |
59 | // When the pccsid is not ISO8859-1, autoconversion is still needed. |
60 | if (Query.pccsid == CCSID_ISO8859_1 && |
61 | (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1)) |
62 | return 0; |
63 | |
64 | // Save the state of std handles before we make changes to it. |
65 | if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) && |
66 | savedStdHandleAutoConversionMode[FD] == -1) |
67 | savedStdHandleAutoConversionMode[FD] = Query.cvtcmd; |
68 | |
69 | if (FD == STDOUT_FILENO || FD == STDERR_FILENO) |
70 | Query.cvtcmd = SETCVTON; |
71 | else |
72 | Query.cvtcmd = SETCVTALL; |
73 | |
74 | Query.pccsid = |
75 | (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) |
76 | ? 0 |
77 | : CCSID_UTF_8; |
78 | // Assume untagged files to be IBM-1047 encoded. |
79 | Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid; |
80 | return fcntl(FD, F_CONTROL_CVT, &Query); |
81 | } |
82 | |
83 | std::error_code llvm::disableAutoConversion(int FD) { |
84 | if (::disableAutoConversion(FD) == -1) |
85 | return std::error_code(errno, std::generic_category()); |
86 | |
87 | return std::error_code(); |
88 | } |
89 | |
90 | std::error_code llvm::enableAutoConversion(int FD) { |
91 | if (::enableAutoConversion(FD) == -1) |
92 | return std::error_code(errno, std::generic_category()); |
93 | |
94 | return std::error_code(); |
95 | } |
96 | |
97 | std::error_code llvm::restoreStdHandleAutoConversion(int FD) { |
98 | if (::restoreStdHandleAutoConversion(FD) == -1) |
99 | return std::error_code(errno, std::generic_category()); |
100 | |
101 | return std::error_code(); |
102 | } |
103 | |
104 | std::error_code llvm::setFileTag(int FD, int CCSID, bool Text) { |
105 | assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) && |
106 | "FT_UNTAGGED and FT_BINARY are not allowed for text files" ); |
107 | struct file_tag Tag; |
108 | Tag.ft_ccsid = CCSID; |
109 | Tag.ft_txtflag = Text; |
110 | Tag.ft_deferred = 0; |
111 | Tag.ft_rsvflags = 0; |
112 | |
113 | if (fcntl(FD, F_SETTAG, &Tag) == -1) |
114 | return std::error_code(errno, std::generic_category()); |
115 | return std::error_code(); |
116 | } |
117 | |
118 | #endif // __MVS__ |
119 | |