]> git.saurik.com Git - bison.git/blame - src/location.c
Fix portability problem on OpenBSD 4.7.
[bison.git] / src / location.c
CommitLineData
8efe435c 1/* Locations for Bison
7d424de1
PE
2
3 Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010 Free
4 Software Foundation, Inc.
8efe435c
AD
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
f16b0819 8 This program is free software: you can redistribute it and/or modify
8efe435c 9 it under the terms of the GNU General Public License as published by
f16b0819
PE
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
8efe435c 12
f16b0819 13 This program is distributed in the hope that it will be useful,
8efe435c
AD
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
f16b0819 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
8efe435c 20
2cec9080 21#include <config.h>
1a715ef2 22#include "system.h"
81ebdef9 23
0c8e079f 24#include <mbswidth.h>
b17a1fc5 25#include <quotearg.h>
8efe435c 26
0c8e079f 27#include "complain.h"
81ebdef9
PE
28#include "location.h"
29
28e52c0d 30location const empty_location = EMPTY_LOCATION_INIT;
b17a1fc5 31
e9071366
AD
32/* If BUF is null, add BUFSIZE (which in this case must be less than
33 INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
34 COLUMN. If an overflow occurs, or might occur but is undetectable,
35 return INT_MAX. Assume COLUMN is nonnegative. */
36
37static inline int
38add_column_width (int column, char const *buf, size_t bufsize)
39{
40 size_t width;
41 unsigned int remaining_columns = INT_MAX - column;
42
43 if (buf)
44 {
45 if (INT_MAX / 2 <= bufsize)
46 return INT_MAX;
47 width = mbsnwidth (buf, bufsize, 0);
48 }
49 else
50 width = bufsize;
51
52 return width <= remaining_columns ? column + width : INT_MAX;
53}
54
55/* Set *LOC and adjust scanner cursor to account for token TOKEN of
56 size SIZE. */
57
58void
59location_compute (location *loc, boundary *cur, char const *token, size_t size)
60{
61 int line = cur->line;
62 int column = cur->column;
63 char const *p0 = token;
64 char const *p = token;
65 char const *lim = token + size;
66
67 loc->start = *cur;
68
69 for (p = token; p < lim; p++)
70 switch (*p)
71 {
72 case '\n':
73 line += line < INT_MAX;
74 column = 1;
75 p0 = p + 1;
76 break;
77
78 case '\t':
79 column = add_column_width (column, p0, p - p0);
80 column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
81 p0 = p + 1;
82 break;
83
84 default:
85 break;
86 }
87
88 cur->line = line;
89 cur->column = column = add_column_width (column, p0, p - p0);
90
91 loc->end = *cur;
92
93 if (line == INT_MAX && loc->start.line != INT_MAX)
94 warn_at (*loc, _("line number overflow"));
95 if (column == INT_MAX && loc->start.column != INT_MAX)
96 warn_at (*loc, _("column number overflow"));
97}
98
99
b17a1fc5
PE
100/* Output to OUT the location LOC.
101 Warning: it uses quotearg's slot 3. */
66381412 102unsigned
81ebdef9 103location_print (FILE *out, location loc)
b17a1fc5 104{
66381412 105 unsigned res = 0;
92822aff 106 int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
66381412
AR
107 res += fprintf (out, "%s",
108 quotearg_n_style (3, escape_quoting_style, loc.start.file));
92822aff
JD
109 if (0 <= loc.start.line)
110 {
66381412 111 res += fprintf(out, ":%d", loc.start.line);
92822aff 112 if (0 <= loc.start.column)
66381412 113 res += fprintf (out, ".%d", loc.start.column);
92822aff 114 }
b17a1fc5 115 if (loc.start.file != loc.end.file)
92822aff 116 {
66381412
AR
117 res += fprintf (out, "-%s",
118 quotearg_n_style (3, escape_quoting_style,
119 loc.end.file));
92822aff
JD
120 if (0 <= loc.end.line)
121 {
66381412 122 res += fprintf(out, ":%d", loc.end.line);
92822aff 123 if (0 <= end_col)
66381412 124 res += fprintf (out, ".%d", end_col);
92822aff
JD
125 }
126 }
127 else if (0 <= loc.end.line)
128 {
129 if (loc.start.line < loc.end.line)
130 {
66381412 131 res += fprintf (out, "-%d", loc.end.line);
92822aff 132 if (0 <= end_col)
66381412 133 res += fprintf (out, ".%d", end_col);
92822aff
JD
134 }
135 else if (0 <= end_col && loc.start.column < end_col)
66381412 136 res += fprintf (out, "-%d", end_col);
92822aff 137 }
66381412
AR
138
139 return res;
b17a1fc5 140}
3fc65ead
JD
141
142void
143boundary_set_from_string (boundary *bound, char *loc_str)
144{
145 /* Must search in reverse since the file name field may
146 * contain `.' or `:'. */
147 char *delim = strrchr (loc_str, '.');
148 aver (delim);
149 *delim = '\0';
150 bound->column = atoi (delim+1);
151 delim = strrchr (loc_str, ':');
152 aver (delim);
153 *delim = '\0';
154 bound->line = atoi (delim+1);
155 bound->file = uniqstr_new (loc_str);
156}