xref: /llvm-project/llvm/lib/Support/AutoConvert.cpp (revision 04379c98638ac3901257b5fa319f9ece828af767)
11527a5e4SAbhina Sreeskantharajan //===- AutoConvert.cpp - Auto conversion between ASCII/EBCDIC -------------===//
21527a5e4SAbhina Sreeskantharajan //
31527a5e4SAbhina Sreeskantharajan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41527a5e4SAbhina Sreeskantharajan // See https://llvm.org/LICENSE.txt for license information.
51527a5e4SAbhina Sreeskantharajan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61527a5e4SAbhina Sreeskantharajan //
71527a5e4SAbhina Sreeskantharajan //===----------------------------------------------------------------------===//
81527a5e4SAbhina Sreeskantharajan //
91527a5e4SAbhina Sreeskantharajan // This file contains functions used for auto conversion between
101527a5e4SAbhina Sreeskantharajan // ASCII/EBCDIC codepages specific to z/OS.
111527a5e4SAbhina Sreeskantharajan //
121527a5e4SAbhina Sreeskantharajan //===----------------------------------------------------------------------===//
131527a5e4SAbhina Sreeskantharajan 
141527a5e4SAbhina Sreeskantharajan #ifdef __MVS__
151527a5e4SAbhina Sreeskantharajan 
161527a5e4SAbhina Sreeskantharajan #include "llvm/Support/AutoConvert.h"
170fe271c3SFanbo Meng #include "llvm/Support/Error.h"
18ab380c28SAbhina Sree #include <cassert>
191527a5e4SAbhina Sreeskantharajan #include <fcntl.h>
201527a5e4SAbhina Sreeskantharajan #include <sys/stat.h>
21ab380c28SAbhina Sree #include <unistd.h>
221527a5e4SAbhina Sreeskantharajan 
23*04379c98SAbhina Sree using namespace llvm;
24*04379c98SAbhina Sree 
25ab380c28SAbhina Sree static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
26ab380c28SAbhina Sree 
27311ac638SAbhina Sree int disablezOSAutoConversion(int FD) {
281527a5e4SAbhina Sreeskantharajan   static const struct f_cnvrt Convert = {
291527a5e4SAbhina Sreeskantharajan       SETCVTOFF, // cvtcmd
301527a5e4SAbhina Sreeskantharajan       0,         // pccsid
31ab380c28SAbhina Sree       0,         // fccsid
321527a5e4SAbhina Sreeskantharajan   };
33ab380c28SAbhina Sree 
34ab380c28SAbhina Sree   return fcntl(FD, F_CONTROL_CVT, &Convert);
351527a5e4SAbhina Sreeskantharajan }
361527a5e4SAbhina Sreeskantharajan 
37311ac638SAbhina Sree int restorezOSStdHandleAutoConversion(int FD) {
38ab380c28SAbhina Sree   assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
39ab380c28SAbhina Sree   if (savedStdHandleAutoConversionMode[FD] == -1)
40ab380c28SAbhina Sree     return 0;
41ab380c28SAbhina Sree   struct f_cnvrt Cvt = {
42ab380c28SAbhina Sree       savedStdHandleAutoConversionMode[FD], // cvtcmd
43ab380c28SAbhina Sree       0,                                    // pccsid
44ab380c28SAbhina Sree       0,                                    // fccsid
45ab380c28SAbhina Sree   };
46ab380c28SAbhina Sree   return (fcntl(FD, F_CONTROL_CVT, &Cvt));
47ab380c28SAbhina Sree }
48ab380c28SAbhina Sree 
49311ac638SAbhina Sree int enablezOSAutoConversion(int FD) {
501527a5e4SAbhina Sreeskantharajan   struct f_cnvrt Query = {
511527a5e4SAbhina Sreeskantharajan       QUERYCVT, // cvtcmd
521527a5e4SAbhina Sreeskantharajan       0,        // pccsid
531527a5e4SAbhina Sreeskantharajan       0,        // fccsid
541527a5e4SAbhina Sreeskantharajan   };
551527a5e4SAbhina Sreeskantharajan 
561527a5e4SAbhina Sreeskantharajan   if (fcntl(FD, F_CONTROL_CVT, &Query) == -1)
57ab380c28SAbhina Sree     return -1;
581527a5e4SAbhina Sreeskantharajan 
59ab380c28SAbhina Sree   // We don't need conversion for UTF-8 tagged files.
60ab380c28SAbhina Sree   // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve
61ab380c28SAbhina Sree   // problems related to UTF-8 tagged source files.
62ab380c28SAbhina Sree   // When the pccsid is not ISO8859-1, autoconversion is still needed.
63ab380c28SAbhina Sree   if (Query.pccsid == CCSID_ISO8859_1 &&
64ab380c28SAbhina Sree       (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1))
65ab380c28SAbhina Sree     return 0;
66ab380c28SAbhina Sree 
67ab380c28SAbhina Sree   // Save the state of std handles before we make changes to it.
68ab380c28SAbhina Sree   if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) &&
69ab380c28SAbhina Sree       savedStdHandleAutoConversionMode[FD] == -1)
70ab380c28SAbhina Sree     savedStdHandleAutoConversionMode[FD] = Query.cvtcmd;
71ab380c28SAbhina Sree 
72ab380c28SAbhina Sree   if (FD == STDOUT_FILENO || FD == STDERR_FILENO)
73ab380c28SAbhina Sree     Query.cvtcmd = SETCVTON;
74ab380c28SAbhina Sree   else
751527a5e4SAbhina Sreeskantharajan     Query.cvtcmd = SETCVTALL;
76ab380c28SAbhina Sree 
771527a5e4SAbhina Sreeskantharajan   Query.pccsid =
781527a5e4SAbhina Sreeskantharajan       (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO)
791527a5e4SAbhina Sreeskantharajan           ? 0
801527a5e4SAbhina Sreeskantharajan           : CCSID_UTF_8;
811527a5e4SAbhina Sreeskantharajan   // Assume untagged files to be IBM-1047 encoded.
821527a5e4SAbhina Sreeskantharajan   Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
83ab380c28SAbhina Sree   return fcntl(FD, F_CONTROL_CVT, &Query);
84ab380c28SAbhina Sree }
85ab380c28SAbhina Sree 
86311ac638SAbhina Sree std::error_code llvm::disablezOSAutoConversion(int FD) {
87311ac638SAbhina Sree   if (::disablezOSAutoConversion(FD) == -1)
88ba13fa2aSMichael Spencer     return errnoAsErrorCode();
89ab380c28SAbhina Sree 
90ab380c28SAbhina Sree   return std::error_code();
91ab380c28SAbhina Sree }
92ab380c28SAbhina Sree 
93311ac638SAbhina Sree std::error_code llvm::enablezOSAutoConversion(int FD) {
94311ac638SAbhina Sree   if (::enablezOSAutoConversion(FD) == -1)
95ba13fa2aSMichael Spencer     return errnoAsErrorCode();
96ab380c28SAbhina Sree 
97ab380c28SAbhina Sree   return std::error_code();
98ab380c28SAbhina Sree }
99ab380c28SAbhina Sree 
100311ac638SAbhina Sree std::error_code llvm::restorezOSStdHandleAutoConversion(int FD) {
101311ac638SAbhina Sree   if (::restorezOSStdHandleAutoConversion(FD) == -1)
102ba13fa2aSMichael Spencer     return errnoAsErrorCode();
103ab380c28SAbhina Sree 
1046a128750SAbhina Sreeskantharajan   return std::error_code();
1051527a5e4SAbhina Sreeskantharajan }
1061527a5e4SAbhina Sreeskantharajan 
107311ac638SAbhina Sree std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
1081527a5e4SAbhina Sreeskantharajan   assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
1091527a5e4SAbhina Sreeskantharajan          "FT_UNTAGGED and FT_BINARY are not allowed for text files");
1101527a5e4SAbhina Sreeskantharajan   struct file_tag Tag;
1111527a5e4SAbhina Sreeskantharajan   Tag.ft_ccsid = CCSID;
1121527a5e4SAbhina Sreeskantharajan   Tag.ft_txtflag = Text;
1131527a5e4SAbhina Sreeskantharajan   Tag.ft_deferred = 0;
1141527a5e4SAbhina Sreeskantharajan   Tag.ft_rsvflags = 0;
1151527a5e4SAbhina Sreeskantharajan 
1166a128750SAbhina Sreeskantharajan   if (fcntl(FD, F_SETTAG, &Tag) == -1)
117ba13fa2aSMichael Spencer     return errnoAsErrorCode();
1186a128750SAbhina Sreeskantharajan   return std::error_code();
1191527a5e4SAbhina Sreeskantharajan }
1201527a5e4SAbhina Sreeskantharajan 
121*04379c98SAbhina Sree ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) {
122*04379c98SAbhina Sree   // If we have a file descriptor, use it to find out file tagging. Otherwise we
123*04379c98SAbhina Sree   // need to use stat() with the file path.
124*04379c98SAbhina Sree   if (FD != -1) {
125*04379c98SAbhina Sree     struct f_cnvrt Query = {
126*04379c98SAbhina Sree         QUERYCVT, // cvtcmd
127*04379c98SAbhina Sree         0,        // pccsid
128*04379c98SAbhina Sree         0,        // fccsid
129*04379c98SAbhina Sree     };
130*04379c98SAbhina Sree     if (fcntl(FD, F_CONTROL_CVT, &Query) == -1)
131*04379c98SAbhina Sree       return std::error_code(errno, std::generic_category());
132*04379c98SAbhina Sree     return Query.fccsid;
133*04379c98SAbhina Sree   }
134*04379c98SAbhina Sree   struct stat Attr;
135*04379c98SAbhina Sree   if (stat(FileName, &Attr) == -1)
136*04379c98SAbhina Sree     return std::error_code(errno, std::generic_category());
137*04379c98SAbhina Sree   return Attr.st_tag.ft_ccsid;
138*04379c98SAbhina Sree }
139*04379c98SAbhina Sree 
140*04379c98SAbhina Sree ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
141*04379c98SAbhina Sree   ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(FileName, FD);
142*04379c98SAbhina Sree   if (std::error_code EC = Ccsid.getError())
143*04379c98SAbhina Sree     return EC;
144*04379c98SAbhina Sree   // We don't need conversion for UTF-8 tagged files or binary files.
145*04379c98SAbhina Sree   // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve
146*04379c98SAbhina Sree   // problems related to UTF-8 tagged source files.
147*04379c98SAbhina Sree   switch (*Ccsid) {
148*04379c98SAbhina Sree   case CCSID_UTF_8:
149*04379c98SAbhina Sree   case CCSID_ISO8859_1:
150*04379c98SAbhina Sree   case FT_BINARY:
151*04379c98SAbhina Sree     return false;
152*04379c98SAbhina Sree   default:
153*04379c98SAbhina Sree     return true;
154*04379c98SAbhina Sree   }
155*04379c98SAbhina Sree }
156*04379c98SAbhina Sree 
1571527a5e4SAbhina Sreeskantharajan #endif //__MVS__
158