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