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