source: cfg_itronx+oil_gcc/toppers/itronx/preprocess.cpp@ 165

Last change on this file since 165 was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 7.8 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2007-2011 by TAKAGI Nobuhisa
6 *
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 */
37#include <cstring>
38#include <algorithm>
39#include <iostream>
40#include <iterator>
41#include "toppers/io.hpp"
42#include "toppers/cpp.hpp"
43#include "toppers/global.hpp"
44#include "toppers/diagnostics.hpp"
45#include "toppers/misc.hpp"
46#include "toppers/itronx/preprocess.hpp"
47#include <boost/spirit/include/classic.hpp>
48
49namespace toppers
50{
51 namespace itronx
52 {
53
54 /*!
55 * \brief 静的API `INCLUDE'の展開
56 * \param[in] in 入力ファイルの内容
57 * \param[out] out 出力ファイルの内容
58 * \param[in] codeset 文字コード
59 * \param[out] dependencies 依存関係の格納先(NULLの場合は格納しない)
60 * \param[out] onces #pragma onceが記述されていたファイル名の格納先(NULLの場合は格納しない)
61 *
62 * `INCLUDE' の引数は、μITRON 仕様のものとは異なり、二重引用符で囲まずに #include 指令と
63 * 同じ形式を用いる。
64 */
65 void expand_include( text const& in, text& out, codeset_t codeset, std::set< std::string >* dependencies, std::set< std::string >* onces )
66 {
67 typedef text::container::const_iterator const_row_iterator;
68 typedef std::string::size_type size_type;
69 size_type const npos = std::string::npos;
70 const_row_iterator first( in.begin().get_row() ), last( in.end().get_row() );
71
72 out.set_line( first->line.file, first->line.line );
73 for ( const_row_iterator iter( first ); iter != last; ++iter )
74 {
75 std::string const& buf = iter->buf;
76 char state = 0;
77
78 for ( size_type i = 0, n = buf.size(); i != n; ++i )
79 {
80 char c = buf[i];
81 if ( c == '\'' || c == '\"' )
82 {
83 if ( state == 0 )
84 {
85 state = c; // 文字(列)リテラル開始
86 }
87 else if ( buf[i - 1] != '\\' ) // \' または \" ではない
88 {
89 state = 0; // 文字(列)リテラル終了
90 }
91 else if ( ( codeset == shift_jis ) && ( i >= 2 ) && is_lead< shift_jis >( buf[i - 2] ) )
92 {
93 state = 0;
94 }
95 out.push_back( c );
96 }
97 else if ( state != 0 ) // 文字(列)リテラル内
98 {
99 out.push_back( c );
100 }
101 else
102 {
103 using namespace boost::spirit::classic;
104 std::string headername;
105 if ( iter == last )
106 {
107 return;
108 }
109 text::const_iterator iter2( iter, i );
110 if ( iter2 == in.end() )
111 {
112 break;
113 }
114 parse_info< text::const_iterator > info
115 = parse( iter2, in.end(),
116 ( str_p( "INCLUDE" ) >> *space_p
117 >> '(' >> *space_p
118 >> '\"' >> ( +( anychar_p - '\"' ) )[ assign( headername ) ] >> '\"' >> *space_p
119 >> ')' >> *space_p >> ';' ) ); // 行番号がずれるので、スキップパーサは使用しない
120 if ( info.hit )
121 {
122 std::vector< std::string > include_paths = get_global< std::vector< std::string > >( "include-path" );
123 std::string hname = search_include_file( include_paths.begin(), include_paths.end(), headername );
124 if ( hname.empty() ) // ヘッダ名が見つからない
125 {
126 fatal( iter->line, _( "cannot open file `%1%\'" ), headername );
127 }
128 else if ( onces == 0 || onces->find( hname ) == onces->end() )
129 {
130 if ( dependencies != 0 )
131 {
132 dependencies->insert( dir_delimiter_to_slash( hname ) );
133 }
134 out.push_back( ' ' ); // ダミーを挿入しておかないと行番号がずれる
135 preprocess( hname, out, codeset, dependencies, onces ); // ヘッダ名で指定されたファイルに対して前処理を再帰的に行う
136 iter = info.stop.get_row();
137 i = info.stop.get_col() - 1;
138 if ( iter != last )
139 {
140 out.set_line( iter->line.file, iter->line.line );
141 }
142 }
143 }
144 else
145 {
146 if ( iter2.get_col() == 0 )
147 {
148 info = parse( iter2, in.end(),
149 ( *( space_p - eol_p ) >>
150 ch_p( '#' ) >> *( space_p - eol_p ) >> "pragma" >> *( space_p - eol_p )
151 >> "once"
152 >> *( space_p - eol_p ) >> eol_p ) );
153 if ( info.hit )
154 {
155 if ( onces != 0 )
156 {
157 onces->insert( iter2.line().file );
158 }
159 out.push_back( '\n' );
160 iter = info.stop.get_row();
161 --iter; // インクリメントされるのでいったん戻す。
162 break;
163 }
164 }
165 if ( parse( iter2, in.end(),
166 ( str_p( "INCLUDE" ) >> *space_p >> '(' >> +( anychar_p - ')' ) >> ')' >> *space_p >> ';' ) ).hit )
167 {
168 warning( iter->line, _( "probably, %1% argument of `%2%\' is illegal" ), _( "1st" ), "INCLUDE" );
169 }
170 out.push_back( c );
171 }
172 }
173 }
174 }
175 }
176
177 /*!
178 * \brief コンフィギュレーションファイルの前処理
179 * \param[in] file コンフィギュレーションファイル名
180 * \param[out] result 前処理後の内容
181 * \param[in] codeset 文字コード
182 * \param[out] dependencies 依存関係の格納先(NULLの場合は格納しない)
183 * \param[out] onces #pragma onceが記述されていたファイル名の格納先(NULLの場合は格納しない)
184 */
185 void preprocess( std::string const& file, text& result, codeset_t codeset, std::set< std::string >* dependencies, std::set< std::string >* onces )
186 {
187 std::string buf;
188 read( file, buf );
189 if ( buf.empty() )
190 {
191 return;
192 }
193 text txt;
194 txt.set_line( file, 1 );
195 remove_comment( buf.begin(), buf.end(), std::back_inserter( txt ), codeset );
196 expand_include( txt, result, codeset, dependencies, onces );
197 }
198
199 }
200}
Note: See TracBrowser for help on using the repository browser.