1cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Locations for Bison 2cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2002, 2005-2012 Free Software Foundation, Inc. 4cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 5cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project This file is part of Bison, the GNU Compiler Compiler. 6cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify 8cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project it under the terms of the GNU General Public License as published by 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation, either version 3 of the License, or 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 11cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 13cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project but WITHOUT ANY WARRANTY; without even the implied warranty of 14cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project GNU General Public License for more details. 16cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 17cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project You should have received a copy of the GNU General Public License 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 20cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <config.h> 21cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "system.h" 22cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <mbswidth.h> 24cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <quotearg.h> 25cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "complain.h" 27cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "location.h" 28cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocation const empty_location = EMPTY_LOCATION_INIT; 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* If BUF is null, add BUFSIZE (which in this case must be less than 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang COLUMN. If an overflow occurs, or might occur but is undetectable, 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return INT_MAX. Assume COLUMN is nonnegative. */ 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wangadd_column_width (int column, char const *buf, size_t bufsize) 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t width; 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int remaining_columns = INT_MAX - column; 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (buf) 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (INT_MAX / 2 <= bufsize) 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return INT_MAX; 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang width = mbsnwidth (buf, bufsize, 0); 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang width = bufsize; 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return width <= remaining_columns ? column + width : INT_MAX; 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Set *LOC and adjust scanner cursor to account for token TOKEN of 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang size SIZE. */ 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocation_compute (location *loc, boundary *cur, char const *token, size_t size) 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int line = cur->line; 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang int column = cur->column; 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang char const *p0 = token; 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang char const *p = token; 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang char const *lim = token + size; 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang loc->start = *cur; 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (p = token; p < lim; p++) 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang switch (*p) 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang case '\n': 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang line += line < INT_MAX; 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang column = 1; 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang p0 = p + 1; 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang case '\t': 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang column = add_column_width (column, p0, p - p0); 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang column = add_column_width (column, NULL, 8 - ((column - 1) & 7)); 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang p0 = p + 1; 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang default: 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang cur->line = line; 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cur->column = column = add_column_width (column, p0, p - p0); 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang loc->end = *cur; 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (line == INT_MAX && loc->start.line != INT_MAX) 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang warn_at (*loc, _("line number overflow")); 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (column == INT_MAX && loc->start.column != INT_MAX) 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang warn_at (*loc, _("column number overflow")); 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 98cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 99cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Output to OUT the location LOC. 100cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project Warning: it uses quotearg's slot 3. */ 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wangunsigned 102cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectlocation_print (FILE *out, location loc) 103cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{ 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned res = 0; 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0; 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, "%s", 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang quotearg_n_style (3, escape_quoting_style, loc.start.file)); 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= loc.start.line) 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, ":%d", loc.start.line); 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= loc.start.column) 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, ".%d", loc.start.column); 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 114cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (loc.start.file != loc.end.file) 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, "-%s", 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang quotearg_n_style (3, escape_quoting_style, 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang loc.end.file)); 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= loc.end.line) 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, ":%d", loc.end.line); 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= end_col) 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, ".%d", end_col); 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (0 <= loc.end.line) 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (loc.start.line < loc.end.line) 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, "-%d", loc.end.line); 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= end_col) 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, ".%d", end_col); 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (0 <= end_col && loc.start.column < end_col) 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang res += fprintf (out, "-%d", end_col); 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return res; 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Persistant data used by location_caret to avoid reopening and rereading the 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang same file all over for each error. */ 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstruct caret_info 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang FILE *source; 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t line; 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t offset; 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}; 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic struct caret_info caret_info = { NULL, 1, 0 }; 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wangcleanup_caret () 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (caret_info.source) 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang fclose (caret_info.source); 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocation_caret (FILE *out, location loc) 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* FIXME: find a way to support multifile locations, and only open once each 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang file. That would make the procedure future-proof. */ 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (! (caret_info.source 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (caret_info.source = fopen (loc.start.file, "r"))) 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang || loc.start.column == -1 || loc.start.line == -1) 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return; 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If the line we want to quote is seekable (the same line as the previous 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang location), just seek it. If it was before, we lost track of it, so 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return to the start of file. */ 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (caret_info.line <= loc.start.line) 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang fseek (caret_info.source, caret_info.offset, SEEK_SET); 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang caret_info.line = 1; 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang caret_info.offset = 0; 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang fseek (caret_info.source, caret_info.offset, SEEK_SET); 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Advance to the line's position, keeping track of the offset. */ 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (caret_info.line < loc.start.line) 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang caret_info.line += fgetc (caret_info.source) == '\n'; 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang caret_info.offset = ftell (caret_info.source); 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Read the actual line. Don't update the offset, so that we keep a pointer 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang to the start of the line. */ 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *buf = NULL; 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t size = 0; 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang ssize_t len = getline (&buf, &size, caret_info.source); 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 < len) 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The caret of a multiline location ends with the first line. */ 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int end = loc.start.line != loc.end.line ? len : loc.end.column; 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Quote the file, indent by a single column. */ 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang fputc (' ', out); 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang fwrite (buf, 1, len, out); 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Print the caret, with the same indent as above. */ 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang fprintf (out, " %*s", loc.start.column - 1, ""); 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int i = loc.start.column; 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang fputc ('^', out); 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (++i < end); 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang fputc ('\n', out); 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (buf); 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wangboundary_set_from_string (boundary *bound, char *loc_str) 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Must search in reverse since the file name field may 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * contain `.' or `:'. */ 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *delim = mbsrchr (loc_str, '.'); 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang aver (delim); 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang *delim = '\0'; 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang bound->column = atoi (delim+1); 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang delim = mbsrchr (loc_str, ':'); 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang aver (delim); 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang *delim = '\0'; 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang bound->line = atoi (delim+1); 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang bound->file = uniqstr_new (loc_str); 230cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project} 231