xref: /freebsd/contrib/llvm-project/llvm/lib/Support/AutoConvert.cpp (revision 56b17de1e8360fe131d425de20b5e75ff3ea897c)
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