1344a3780SDimitry Andric //===- AutoConvert.cpp - Auto conversion between ASCII/EBCDIC -------------===//
2344a3780SDimitry Andric //
3344a3780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344a3780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5344a3780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344a3780SDimitry Andric //
7344a3780SDimitry Andric //===----------------------------------------------------------------------===//
8344a3780SDimitry Andric //
9344a3780SDimitry Andric // This file contains functions used for auto conversion between
10344a3780SDimitry Andric // ASCII/EBCDIC codepages specific to z/OS.
11344a3780SDimitry Andric //
12344a3780SDimitry Andric //===----------------------------------------------------------------------===//
13344a3780SDimitry Andric
14344a3780SDimitry Andric #ifdef __MVS__
15344a3780SDimitry Andric
16344a3780SDimitry Andric #include "llvm/Support/AutoConvert.h"
17ac9a064cSDimitry Andric #include "llvm/Support/Error.h"
18312c0ed1SDimitry Andric #include <cassert>
19344a3780SDimitry Andric #include <fcntl.h>
20344a3780SDimitry Andric #include <sys/stat.h>
21312c0ed1SDimitry Andric #include <unistd.h>
22344a3780SDimitry Andric
23312c0ed1SDimitry Andric static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
24312c0ed1SDimitry Andric
disableAutoConversion(int FD)25312c0ed1SDimitry Andric int disableAutoConversion(int FD) {
26344a3780SDimitry Andric static const struct f_cnvrt Convert = {
27344a3780SDimitry Andric SETCVTOFF, // cvtcmd
28344a3780SDimitry Andric 0, // pccsid
29312c0ed1SDimitry Andric 0, // fccsid
30344a3780SDimitry Andric };
31312c0ed1SDimitry Andric
32312c0ed1SDimitry Andric return fcntl(FD, F_CONTROL_CVT, &Convert);
33344a3780SDimitry Andric }
34344a3780SDimitry Andric
restoreStdHandleAutoConversion(int FD)35312c0ed1SDimitry Andric int restoreStdHandleAutoConversion(int FD) {
36312c0ed1SDimitry Andric assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
37312c0ed1SDimitry Andric if (savedStdHandleAutoConversionMode[FD] == -1)
38312c0ed1SDimitry Andric return 0;
39312c0ed1SDimitry Andric struct f_cnvrt Cvt = {
40312c0ed1SDimitry Andric savedStdHandleAutoConversionMode[FD], // cvtcmd
41312c0ed1SDimitry Andric 0, // pccsid
42312c0ed1SDimitry Andric 0, // fccsid
43312c0ed1SDimitry Andric };
44312c0ed1SDimitry Andric return (fcntl(FD, F_CONTROL_CVT, &Cvt));
45312c0ed1SDimitry Andric }
46312c0ed1SDimitry Andric
enableAutoConversion(int FD)47312c0ed1SDimitry Andric int enableAutoConversion(int FD) {
48344a3780SDimitry Andric struct f_cnvrt Query = {
49344a3780SDimitry Andric QUERYCVT, // cvtcmd
50344a3780SDimitry Andric 0, // pccsid
51344a3780SDimitry Andric 0, // fccsid
52344a3780SDimitry Andric };
53344a3780SDimitry Andric
54344a3780SDimitry Andric if (fcntl(FD, F_CONTROL_CVT, &Query) == -1)
55312c0ed1SDimitry Andric return -1;
56344a3780SDimitry Andric
57312c0ed1SDimitry Andric // We don't need conversion for UTF-8 tagged files.
58312c0ed1SDimitry Andric // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve
59312c0ed1SDimitry Andric // problems related to UTF-8 tagged source files.
60312c0ed1SDimitry Andric // When the pccsid is not ISO8859-1, autoconversion is still needed.
61312c0ed1SDimitry Andric if (Query.pccsid == CCSID_ISO8859_1 &&
62312c0ed1SDimitry Andric (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1))
63312c0ed1SDimitry Andric return 0;
64312c0ed1SDimitry Andric
65312c0ed1SDimitry Andric // Save the state of std handles before we make changes to it.
66312c0ed1SDimitry Andric if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) &&
67312c0ed1SDimitry Andric savedStdHandleAutoConversionMode[FD] == -1)
68312c0ed1SDimitry Andric savedStdHandleAutoConversionMode[FD] = Query.cvtcmd;
69312c0ed1SDimitry Andric
70312c0ed1SDimitry Andric if (FD == STDOUT_FILENO || FD == STDERR_FILENO)
71312c0ed1SDimitry Andric Query.cvtcmd = SETCVTON;
72312c0ed1SDimitry Andric else
73344a3780SDimitry Andric Query.cvtcmd = SETCVTALL;
74312c0ed1SDimitry Andric
75344a3780SDimitry Andric Query.pccsid =
76344a3780SDimitry Andric (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO)
77344a3780SDimitry Andric ? 0
78344a3780SDimitry Andric : CCSID_UTF_8;
79344a3780SDimitry Andric // Assume untagged files to be IBM-1047 encoded.
80344a3780SDimitry Andric Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
81312c0ed1SDimitry Andric return fcntl(FD, F_CONTROL_CVT, &Query);
82312c0ed1SDimitry Andric }
83312c0ed1SDimitry Andric
disableAutoConversion(int FD)84312c0ed1SDimitry Andric std::error_code llvm::disableAutoConversion(int FD) {
85312c0ed1SDimitry Andric if (::disableAutoConversion(FD) == -1)
86ac9a064cSDimitry Andric return errnoAsErrorCode();
87312c0ed1SDimitry Andric
88312c0ed1SDimitry Andric return std::error_code();
89312c0ed1SDimitry Andric }
90312c0ed1SDimitry Andric
enableAutoConversion(int FD)91312c0ed1SDimitry Andric std::error_code llvm::enableAutoConversion(int FD) {
92312c0ed1SDimitry Andric if (::enableAutoConversion(FD) == -1)
93ac9a064cSDimitry Andric return errnoAsErrorCode();
94312c0ed1SDimitry Andric
95312c0ed1SDimitry Andric return std::error_code();
96312c0ed1SDimitry Andric }
97312c0ed1SDimitry Andric
restoreStdHandleAutoConversion(int FD)98312c0ed1SDimitry Andric std::error_code llvm::restoreStdHandleAutoConversion(int FD) {
99312c0ed1SDimitry Andric if (::restoreStdHandleAutoConversion(FD) == -1)
100ac9a064cSDimitry Andric return errnoAsErrorCode();
101312c0ed1SDimitry Andric
102344a3780SDimitry Andric return std::error_code();
103344a3780SDimitry Andric }
104344a3780SDimitry Andric
setFileTag(int FD,int CCSID,bool Text)105344a3780SDimitry Andric std::error_code llvm::setFileTag(int FD, int CCSID, bool Text) {
106344a3780SDimitry Andric assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
107344a3780SDimitry Andric "FT_UNTAGGED and FT_BINARY are not allowed for text files");
108344a3780SDimitry Andric struct file_tag Tag;
109344a3780SDimitry Andric Tag.ft_ccsid = CCSID;
110344a3780SDimitry Andric Tag.ft_txtflag = Text;
111344a3780SDimitry Andric Tag.ft_deferred = 0;
112344a3780SDimitry Andric Tag.ft_rsvflags = 0;
113344a3780SDimitry Andric
114344a3780SDimitry Andric if (fcntl(FD, F_SETTAG, &Tag) == -1)
115ac9a064cSDimitry Andric return errnoAsErrorCode();
116344a3780SDimitry Andric return std::error_code();
117344a3780SDimitry Andric }
118344a3780SDimitry Andric
119344a3780SDimitry Andric #endif // __MVS__
120