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