xref: /freebsd-src/contrib/llvm-project/llvm/lib/Support/AutoConvert.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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*0fca6ea1SDimitry Andric #include "llvm/Support/Error.h"
185f757f3fSDimitry Andric #include <cassert>
19fe6060f1SDimitry Andric #include <fcntl.h>
20fe6060f1SDimitry Andric #include <sys/stat.h>
215f757f3fSDimitry Andric #include <unistd.h>
22fe6060f1SDimitry Andric 
235f757f3fSDimitry Andric static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
245f757f3fSDimitry Andric 
255f757f3fSDimitry Andric int disableAutoConversion(int FD) {
26fe6060f1SDimitry Andric   static const struct f_cnvrt Convert = {
27fe6060f1SDimitry Andric       SETCVTOFF, // cvtcmd
28fe6060f1SDimitry Andric       0,         // pccsid
295f757f3fSDimitry Andric       0,         // fccsid
30fe6060f1SDimitry Andric   };
315f757f3fSDimitry Andric 
325f757f3fSDimitry Andric   return fcntl(FD, F_CONTROL_CVT, &Convert);
33fe6060f1SDimitry Andric }
34fe6060f1SDimitry Andric 
355f757f3fSDimitry Andric int restoreStdHandleAutoConversion(int FD) {
365f757f3fSDimitry Andric   assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
375f757f3fSDimitry Andric   if (savedStdHandleAutoConversionMode[FD] == -1)
385f757f3fSDimitry Andric     return 0;
395f757f3fSDimitry Andric   struct f_cnvrt Cvt = {
405f757f3fSDimitry Andric       savedStdHandleAutoConversionMode[FD], // cvtcmd
415f757f3fSDimitry Andric       0,                                    // pccsid
425f757f3fSDimitry Andric       0,                                    // fccsid
435f757f3fSDimitry Andric   };
445f757f3fSDimitry Andric   return (fcntl(FD, F_CONTROL_CVT, &Cvt));
455f757f3fSDimitry Andric }
465f757f3fSDimitry Andric 
475f757f3fSDimitry Andric int enableAutoConversion(int FD) {
48fe6060f1SDimitry Andric   struct f_cnvrt Query = {
49fe6060f1SDimitry Andric       QUERYCVT, // cvtcmd
50fe6060f1SDimitry Andric       0,        // pccsid
51fe6060f1SDimitry Andric       0,        // fccsid
52fe6060f1SDimitry Andric   };
53fe6060f1SDimitry Andric 
54fe6060f1SDimitry Andric   if (fcntl(FD, F_CONTROL_CVT, &Query) == -1)
555f757f3fSDimitry Andric     return -1;
56fe6060f1SDimitry Andric 
575f757f3fSDimitry Andric   // We don't need conversion for UTF-8 tagged files.
585f757f3fSDimitry Andric   // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve
595f757f3fSDimitry Andric   // problems related to UTF-8 tagged source files.
605f757f3fSDimitry Andric   // When the pccsid is not ISO8859-1, autoconversion is still needed.
615f757f3fSDimitry Andric   if (Query.pccsid == CCSID_ISO8859_1 &&
625f757f3fSDimitry Andric       (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1))
635f757f3fSDimitry Andric     return 0;
645f757f3fSDimitry Andric 
655f757f3fSDimitry Andric   // Save the state of std handles before we make changes to it.
665f757f3fSDimitry Andric   if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) &&
675f757f3fSDimitry Andric       savedStdHandleAutoConversionMode[FD] == -1)
685f757f3fSDimitry Andric     savedStdHandleAutoConversionMode[FD] = Query.cvtcmd;
695f757f3fSDimitry Andric 
705f757f3fSDimitry Andric   if (FD == STDOUT_FILENO || FD == STDERR_FILENO)
715f757f3fSDimitry Andric     Query.cvtcmd = SETCVTON;
725f757f3fSDimitry Andric   else
73fe6060f1SDimitry Andric     Query.cvtcmd = SETCVTALL;
745f757f3fSDimitry Andric 
75fe6060f1SDimitry Andric   Query.pccsid =
76fe6060f1SDimitry Andric       (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO)
77fe6060f1SDimitry Andric           ? 0
78fe6060f1SDimitry Andric           : CCSID_UTF_8;
79fe6060f1SDimitry Andric   // Assume untagged files to be IBM-1047 encoded.
80fe6060f1SDimitry Andric   Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
815f757f3fSDimitry Andric   return fcntl(FD, F_CONTROL_CVT, &Query);
825f757f3fSDimitry Andric }
835f757f3fSDimitry Andric 
845f757f3fSDimitry Andric std::error_code llvm::disableAutoConversion(int FD) {
855f757f3fSDimitry Andric   if (::disableAutoConversion(FD) == -1)
86*0fca6ea1SDimitry Andric     return errnoAsErrorCode();
875f757f3fSDimitry Andric 
885f757f3fSDimitry Andric   return std::error_code();
895f757f3fSDimitry Andric }
905f757f3fSDimitry Andric 
915f757f3fSDimitry Andric std::error_code llvm::enableAutoConversion(int FD) {
925f757f3fSDimitry Andric   if (::enableAutoConversion(FD) == -1)
93*0fca6ea1SDimitry Andric     return errnoAsErrorCode();
945f757f3fSDimitry Andric 
955f757f3fSDimitry Andric   return std::error_code();
965f757f3fSDimitry Andric }
975f757f3fSDimitry Andric 
985f757f3fSDimitry Andric std::error_code llvm::restoreStdHandleAutoConversion(int FD) {
995f757f3fSDimitry Andric   if (::restoreStdHandleAutoConversion(FD) == -1)
100*0fca6ea1SDimitry Andric     return errnoAsErrorCode();
1015f757f3fSDimitry Andric 
102fe6060f1SDimitry Andric   return std::error_code();
103fe6060f1SDimitry Andric }
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric std::error_code llvm::setFileTag(int FD, int CCSID, bool Text) {
106fe6060f1SDimitry Andric   assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
107fe6060f1SDimitry Andric          "FT_UNTAGGED and FT_BINARY are not allowed for text files");
108fe6060f1SDimitry Andric   struct file_tag Tag;
109fe6060f1SDimitry Andric   Tag.ft_ccsid = CCSID;
110fe6060f1SDimitry Andric   Tag.ft_txtflag = Text;
111fe6060f1SDimitry Andric   Tag.ft_deferred = 0;
112fe6060f1SDimitry Andric   Tag.ft_rsvflags = 0;
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric   if (fcntl(FD, F_SETTAG, &Tag) == -1)
115*0fca6ea1SDimitry Andric     return errnoAsErrorCode();
116fe6060f1SDimitry Andric   return std::error_code();
117fe6060f1SDimitry Andric }
118fe6060f1SDimitry Andric 
119fe6060f1SDimitry Andric #endif // __MVS__
120