]> git.donarmstrong.com Git - lilypond.git/blob - lib/source-file.cc
release: 0.1.11
[lilypond.git] / lib / source-file.cc
1 /*
2   source-file.cc -- implement 
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Jan Nieuwenhuizen <jan@digicash.com> 
7   & Han-Wen Nienhuys <hanwen@stack.nl>
8 */
9
10
11 #include <assert.h>
12 #include <strstream.h>
13
14 #include "string.hh"
15 #include "proto.hh"
16 #include "plist.hh"
17 #include "warn.hh"
18 #include "windhoos-suck-suck-suck-thank-you-cygnus.hh"
19 #include "source-file.hh"
20 #include "file-storage.hh"
21
22 Source_file::Source_file(String filename_str)
23 {
24     name_str_ = filename_str;
25     istream_p_ = 0;
26     storage_p_ = new Simple_file_storage(filename_str);
27 }
28
29 istream*
30 Source_file::istream_l()
31 {
32     if (!name_str_.length_i())
33         return &cin;
34     
35     if (!istream_p_) 
36       {
37         if (length_i()) // can-t this be done without such a hack?
38             istream_p_ = new istrstream(ch_C(), length_i());
39         else 
40           {
41             istream_p_ = new istrstream("", 0);
42             istream_p_->set(ios::eofbit);
43           }
44       }
45     return istream_p_;
46 }
47
48 String
49 Source_file::file_line_no_str(char const *context_ch_C) const
50 {
51   if  (!ch_C())
52     return "(unknown)";
53   else
54     return name_str() + ": "
55         + String(line_i(context_ch_C));
56 }
57
58 String
59 Source_file::name_str() const
60 {
61     return name_str_;
62 }
63
64 Source_file::~Source_file()
65 {
66     delete istream_p_;
67     istream_p_ = 0;
68     delete storage_p_;
69 }
70
71 String
72 Source_file::error_str(char const* pos_ch_C) const
73 {
74     char const* data_ch_C = ch_C();
75     char const * eof_C_ = data_ch_C + length_i();
76     if (!in_b(pos_ch_C))
77         return "(position unknown)";
78
79     
80     if (pos_ch_C == eof_C_)
81         pos_ch_C --;
82     char const* begin_ch_C = pos_ch_C;
83     while (begin_ch_C > data_ch_C)
84         if (*--begin_ch_C == '\n') 
85           {
86             begin_ch_C++;
87             break;
88           }
89
90     char const* end_ch_C = pos_ch_C;
91     while (end_ch_C < eof_C_)
92         if (*end_ch_C++ == '\n') 
93           {
94           end_ch_C--;
95           break;
96           }
97   
98         //    String(char const* p, int length) is missing!?
99     String line_str((Byte const*)begin_ch_C, end_ch_C - begin_ch_C);
100
101     int error_col_i = 0;
102     char const* scan_ch_C = begin_ch_C;
103     while (scan_ch_C < pos_ch_C)
104         if (*scan_ch_C++ == '\t')
105             error_col_i = (error_col_i / 8 + 1) * 8;
106         else
107             error_col_i++;
108
109     String str = line_str.left_str(pos_ch_C - begin_ch_C) 
110         + String('\n')
111         + String(' ', error_col_i) 
112         + line_str.mid_str(pos_ch_C - begin_ch_C, INT_MAX); // String::mid should take 0 arg..
113     return str;
114 }
115
116 bool
117 Source_file::in_b(char const* pos_ch_C) const
118 {
119     return (pos_ch_C && (pos_ch_C >= ch_C()) && (pos_ch_C <= ch_C() + length_i()));
120 }
121
122
123 int
124 Source_file::line_i(char const* pos_ch_C) const
125 {
126     if (!in_b(pos_ch_C))
127         return 0;
128
129     int i = 1;
130     char const* scan_ch_C = ch_C();
131     if (!scan_ch_C)
132       return 0;
133     
134     while (scan_ch_C < pos_ch_C)
135         if (*scan_ch_C++ == '\n')
136                 i++;
137     return i;
138 }
139
140 int
141 Source_file::length_i() const
142 {
143     return storage_p_->length_i();
144 }
145
146 char const *
147 Source_file::ch_C() const
148 {
149     return storage_p_->ch_C();
150 }