Path: blob/main/sys/contrib/dev/acpica/common/acgetline.c
48375 views
/******************************************************************************1*2* Module Name: acgetline - local line editing3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/amlcode.h>154#include <contrib/dev/acpica/include/acparser.h>155#include <contrib/dev/acpica/include/acdebug.h>156157/*158* This is an os-independent implementation of line-editing services needed159* by the AcpiExec utility. It uses getchar() and putchar() and the existing160* history support provided by the AML debugger. It assumes that the terminal161* is in the correct line-editing mode such as raw and noecho. The OSL162* interface AcpiOsInitialize should do this. AcpiOsTerminate should put the163* terminal back into the original mode.164*/165#define _COMPONENT ACPI_OS_SERVICES166ACPI_MODULE_NAME ("acgetline")167168169/* Local prototypes */170171static void172AcpiAcClearLine (173UINT32 EndOfLine,174UINT32 CursorPosition);175176/* Various ASCII constants */177178#define _ASCII_NUL 0179#define _ASCII_BACKSPACE 0x08180#define _ASCII_TAB 0x09181#define _ASCII_ESCAPE 0x1B182#define _ASCII_SPACE 0x20183#define _ASCII_LEFT_BRACKET 0x5B184#define _ASCII_DEL 0x7F185#define _ASCII_UP_ARROW 'A'186#define _ASCII_DOWN_ARROW 'B'187#define _ASCII_RIGHT_ARROW 'C'188#define _ASCII_LEFT_ARROW 'D'189#define _ASCII_NEWLINE '\n'190191/* Erase a single character on the input command line */192193#define ACPI_CLEAR_CHAR() \194putchar (_ASCII_BACKSPACE); \195putchar (_ASCII_SPACE); \196putchar (_ASCII_BACKSPACE);197198/* Backup cursor by Count positions */199200#define ACPI_BACKUP_CURSOR(i, Count) \201for (i = 0; i < (Count); i++) \202{putchar (_ASCII_BACKSPACE);}203204205/******************************************************************************206*207* FUNCTION: AcpiAcClearLine208*209* PARAMETERS: EndOfLine - Current end-of-line index210* CursorPosition - Current cursor position within line211*212* RETURN: None213*214* DESCRIPTION: Clear the entire command line the hard way, but probably the215* most portable.216*217*****************************************************************************/218219static void220AcpiAcClearLine (221UINT32 EndOfLine,222UINT32 CursorPosition)223{224UINT32 i;225226227if (CursorPosition < EndOfLine)228{229/* Clear line from current position to end of line */230231for (i = 0; i < (EndOfLine - CursorPosition); i++)232{233putchar (' ');234}235}236237/* Clear the entire line */238239for (; EndOfLine > 0; EndOfLine--)240{241ACPI_CLEAR_CHAR ();242}243}244245246/******************************************************************************247*248* FUNCTION: AcpiOsGetLine249*250* PARAMETERS: Buffer - Where to return the command line251* BufferLength - Maximum length of Buffer252* BytesRead - Where the actual byte count is returned253*254* RETURN: Status and actual bytes read255*256* DESCRIPTION: Get the next input line from the terminal. NOTE: terminal257* is expected to be in a mode that supports line-editing (raw,258* noecho). This function is intended to be very portable. Also,259* it uses the history support implemented in the AML debugger.260*261*****************************************************************************/262263ACPI_STATUS264AcpiOsGetLine (265char *Buffer,266UINT32 BufferLength,267UINT32 *BytesRead)268{269char *NextCommand;270UINT32 MaxCommandIndex = AcpiGbl_NextCmdNum - 1;271UINT32 CurrentCommandIndex = MaxCommandIndex;272UINT32 PreviousCommandIndex = MaxCommandIndex;273int InputChar;274UINT32 CursorPosition = 0;275UINT32 EndOfLine = 0;276UINT32 i;277278279/* Always clear the line buffer before we read a new line */280281memset (Buffer, 0, BufferLength);282283/*284* This loop gets one character at a time (except for esc sequences)285* until a newline or error is detected.286*287* Note: Don't attempt to write terminal control ESC sequences, even288* though it makes certain things more difficult.289*/290while (1)291{292if (EndOfLine >= (BufferLength - 1))293{294return (AE_BUFFER_OVERFLOW);295}296297InputChar = getchar ();298switch (InputChar)299{300default: /* This is the normal character case */301302/* Echo the character (at EOL) and copy it to the line buffer */303304if (EndOfLine == CursorPosition)305{306putchar (InputChar);307Buffer[EndOfLine] = (char) InputChar;308309EndOfLine++;310CursorPosition++;311Buffer[EndOfLine] = 0;312continue;313}314315/* Insert character into the middle of the buffer */316317memmove (&Buffer[CursorPosition + 1], &Buffer[CursorPosition],318(EndOfLine - CursorPosition + 1));319320Buffer [CursorPosition] = (char) InputChar;321Buffer [EndOfLine + 1] = 0;322323/* Display the new part of line starting at the new character */324325fprintf (stdout, "%s", &Buffer[CursorPosition]);326327/* Restore cursor */328329ACPI_BACKUP_CURSOR (i, EndOfLine - CursorPosition);330CursorPosition++;331EndOfLine++;332continue;333334case _ASCII_DEL: /* Backspace key */335336if (!EndOfLine) /* Any characters on the command line? */337{338continue;339}340341if (EndOfLine == CursorPosition) /* Erase the final character */342{343ACPI_CLEAR_CHAR ();344EndOfLine--;345CursorPosition--;346continue;347}348349if (!CursorPosition) /* Do not backup beyond start of line */350{351continue;352}353354/* Remove the character from the line */355356memmove (&Buffer[CursorPosition - 1], &Buffer[CursorPosition],357(EndOfLine - CursorPosition + 1));358359/* Display the new part of line starting at the new character */360361putchar (_ASCII_BACKSPACE);362fprintf (stdout, "%s ", &Buffer[CursorPosition - 1]);363364/* Restore cursor */365366ACPI_BACKUP_CURSOR (i, EndOfLine - CursorPosition + 1);367EndOfLine--;368369if (CursorPosition > 0)370{371CursorPosition--;372}373continue;374375case _ASCII_NEWLINE: /* Normal exit case at end of command line */376case _ASCII_NUL:377378/* Return the number of bytes in the command line string */379380if (BytesRead)381{382*BytesRead = EndOfLine;383}384385/* Echo, terminate string buffer, and exit */386387putchar (InputChar);388Buffer[EndOfLine] = 0;389return (AE_OK);390391case _ASCII_TAB:392393/* Ignore */394395continue;396397case EOF:398399return (AE_ERROR);400401case _ASCII_ESCAPE:402403/* Check for escape sequences of the form "ESC[x" */404405InputChar = getchar ();406if (InputChar != _ASCII_LEFT_BRACKET)407{408continue; /* Ignore this ESC, does not have the '[' */409}410411/* Get the code following the ESC [ */412413InputChar = getchar (); /* Backup one character */414switch (InputChar)415{416case _ASCII_LEFT_ARROW:417418if (CursorPosition > 0)419{420putchar (_ASCII_BACKSPACE);421CursorPosition--;422}423continue;424425case _ASCII_RIGHT_ARROW:426/*427* Move one character forward. Do this without sending428* ESC sequence to the terminal for max portability.429*/430if (CursorPosition < EndOfLine)431{432/* Backup to start of line and print the entire line */433434ACPI_BACKUP_CURSOR (i, CursorPosition);435fprintf (stdout, "%s", Buffer);436437/* Backup to where the cursor should be */438439CursorPosition++;440ACPI_BACKUP_CURSOR (i, EndOfLine - CursorPosition);441}442continue;443444case _ASCII_UP_ARROW:445446/* If no commands available or at start of history list, ignore */447448if (!CurrentCommandIndex)449{450continue;451}452453/* Manage our up/down progress */454455if (CurrentCommandIndex > PreviousCommandIndex)456{457CurrentCommandIndex = PreviousCommandIndex;458}459460/* Get the historical command from the debugger */461462NextCommand = AcpiDbGetHistoryByIndex (CurrentCommandIndex);463if (!NextCommand)464{465return (AE_ERROR);466}467468/* Make this the active command and echo it */469470AcpiAcClearLine (EndOfLine, CursorPosition);471strcpy (Buffer, NextCommand);472fprintf (stdout, "%s", Buffer);473EndOfLine = CursorPosition = strlen (Buffer);474475PreviousCommandIndex = CurrentCommandIndex;476CurrentCommandIndex--;477continue;478479case _ASCII_DOWN_ARROW:480481if (!MaxCommandIndex) /* Any commands available? */482{483continue;484}485486/* Manage our up/down progress */487488if (CurrentCommandIndex < PreviousCommandIndex)489{490CurrentCommandIndex = PreviousCommandIndex;491}492493/* If we are the end of the history list, output a clear new line */494495if ((CurrentCommandIndex + 1) > MaxCommandIndex)496{497AcpiAcClearLine (EndOfLine, CursorPosition);498EndOfLine = CursorPosition = 0;499PreviousCommandIndex = CurrentCommandIndex;500continue;501}502503PreviousCommandIndex = CurrentCommandIndex;504CurrentCommandIndex++;505506/* Get the historical command from the debugger */507508NextCommand = AcpiDbGetHistoryByIndex (CurrentCommandIndex);509if (!NextCommand)510{511return (AE_ERROR);512}513514/* Make this the active command and echo it */515516AcpiAcClearLine (EndOfLine, CursorPosition);517strcpy (Buffer, NextCommand);518fprintf (stdout, "%s", Buffer);519EndOfLine = CursorPosition = strlen (Buffer);520continue;521522case 0x31:523case 0x32:524case 0x33:525case 0x34:526case 0x35:527case 0x36:528/*529* Ignore the various keys like insert/delete/home/end, etc.530* But we must eat the final character of the ESC sequence.531*/532(void) getchar ();533continue;534535default:536537/* Ignore random escape sequences that we don't care about */538539continue;540}541continue;542}543}544}545546547