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 "llvm/Support/Error.h" |
18 | #include <cassert> |
19 | #include <fcntl.h> |
20 | #include <sys/stat.h> |
21 | #include <unistd.h> |
22 | |
23 | static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1}; |
24 | |
25 | int disableAutoConversion(int FD) { |
26 | static const struct f_cnvrt Convert = { |
27 | SETCVTOFF, // cvtcmd |
28 | 0, // pccsid |
29 | 0, // fccsid |
30 | }; |
31 | |
32 | return fcntl(FD, F_CONTROL_CVT, &Convert); |
33 | } |
34 | |
35 | int restoreStdHandleAutoConversion(int FD) { |
36 | assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO); |
37 | if (savedStdHandleAutoConversionMode[FD] == -1) |
38 | return 0; |
39 | struct f_cnvrt Cvt = { |
40 | savedStdHandleAutoConversionMode[FD], // cvtcmd |
41 | 0, // pccsid |
42 | 0, // fccsid |
43 | }; |
44 | return (fcntl(FD, F_CONTROL_CVT, &Cvt)); |
45 | } |
46 | |
47 | int enableAutoConversion(int FD) { |
48 | struct f_cnvrt Query = { |
49 | QUERYCVT, // cvtcmd |
50 | 0, // pccsid |
51 | 0, // fccsid |
52 | }; |
53 | |
54 | if (fcntl(FD, F_CONTROL_CVT, &Query) == -1) |
55 | return -1; |
56 | |
57 | // We don't need conversion for UTF-8 tagged files. |
58 | // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve |
59 | // problems related to UTF-8 tagged source files. |
60 | // When the pccsid is not ISO8859-1, autoconversion is still needed. |
61 | if (Query.pccsid == CCSID_ISO8859_1 && |
62 | (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1)) |
63 | return 0; |
64 | |
65 | // Save the state of std handles before we make changes to it. |
66 | if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) && |
67 | savedStdHandleAutoConversionMode[FD] == -1) |
68 | savedStdHandleAutoConversionMode[FD] = Query.cvtcmd; |
69 | |
70 | if (FD == STDOUT_FILENO || FD == STDERR_FILENO) |
71 | Query.cvtcmd = SETCVTON; |
72 | else |
73 | Query.cvtcmd = SETCVTALL; |
74 | |
75 | Query.pccsid = |
76 | (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) |
77 | ? 0 |
78 | : CCSID_UTF_8; |
79 | // Assume untagged files to be IBM-1047 encoded. |
80 | Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid; |
81 | return fcntl(FD, F_CONTROL_CVT, &Query); |
82 | } |
83 | |
84 | std::error_code llvm::disableAutoConversion(int FD) { |
85 | if (::disableAutoConversion(FD) == -1) |
86 | return errnoAsErrorCode(); |
87 | |
88 | return std::error_code(); |
89 | } |
90 | |
91 | std::error_code llvm::enableAutoConversion(int FD) { |
92 | if (::enableAutoConversion(FD) == -1) |
93 | return errnoAsErrorCode(); |
94 | |
95 | return std::error_code(); |
96 | } |
97 | |
98 | std::error_code llvm::restoreStdHandleAutoConversion(int FD) { |
99 | if (::restoreStdHandleAutoConversion(FD) == -1) |
100 | return errnoAsErrorCode(); |
101 | |
102 | return std::error_code(); |
103 | } |
104 | |
105 | std::error_code llvm::setFileTag(int FD, int CCSID, bool Text) { |
106 | assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) && |
107 | "FT_UNTAGGED and FT_BINARY are not allowed for text files" ); |
108 | struct file_tag Tag; |
109 | Tag.ft_ccsid = CCSID; |
110 | Tag.ft_txtflag = Text; |
111 | Tag.ft_deferred = 0; |
112 | Tag.ft_rsvflags = 0; |
113 | |
114 | if (fcntl(FD, F_SETTAG, &Tag) == -1) |
115 | return errnoAsErrorCode(); |
116 | return std::error_code(); |
117 | } |
118 | |
119 | #endif // __MVS__ |
120 | |