resources.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-------------------------> GNU Sather - sourcefile <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute and/or modify it under the terms of the GNU Library General --
-- Public License (LGPL) as published by the Free Software Foundation; --
-- either version 2 of the license, or (at your option) any later version. --
-- This library is distributed in the hope that it will be useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details. --
-- The license text is also available from: Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
--------------> Please email comments to <bug-sather@gnu.org> <--------------
class RESOURCES
class RESOURCES is
-- This class provides the mechanism whereby a program may at run-time
-- read text strings as resources needed for use in the current cultural
-- context.
-- Version 1.2 Jun 97. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 10 Dec 96 kh Original
-- 19 Feb 97 kh Additions for string/char portability.
-- 26 Jun 97 kh Provide for Level 5 of ISO/IEC 14652
private attr lib : LIBCHARS ;
-- Only one of the following so default knows whether to
-- create or not
private shared priv_default : SAME ;
private attr class_map : FMAP{STR,FILE_PATH} ;
Leaf_Name_ref : STR is
-- This routine creates and returns the repertoire map file name "lib_res",
-- which needs to be inthe default local culture and encoding, not the culture
-- for which this is a resource.
-- resources/en_NZ/lib_res
loc_lib : LIBCHARS := LIBCHARS::default ;
loc_res : CODE_STR := CODE_STR::create(loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_L.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_I.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_B.card,loc_lib) +
CHAR_CODE::create(UNICODE::LOW_LINE.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_R.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_E.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_S.card,loc_lib) ;
return loc_res.tgt_str
end ;
private Lib_Res_ref : STR is
-- This routine creates and returns the repertoire map file name "SATHER_RESOURCES", using
-- the local culture repertoire and encoding, not that of the culture for
-- which this is a resource object.
loc_lib : LIBCHARS := LIBCHARS::default ;
loc_res : CODE_STR := CODE_STR::create(loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_S.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_A.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_T.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_H.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_E.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_R.card,loc_lib) +
CHAR_CODE::create(UNICODE::LOW_LINE.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_R.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_E.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_S.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_O.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_U.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_R.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_C.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_E.card,loc_lib) +
CHAR_CODE::create(UNICODE::LATIN_CAPITAL_LETTER_S.card,loc_lib) ;
return loc_res.tgt_str
end ;
private search_file( file_path : FILE_PATH )
pre ~void(file_path)
post true
is
-- This routine calls itself recursively as necessary to build up a map
-- of all of the class resource file names held in a single library. If the
-- file is inaccessible then the routine returns quietly.
lib_head : FILE_PATH := file_path.head ;-- needed for leaf name building!
fyle : TEXT_FILE := TEXT_FILE::open_for_read(file_path.str) ;
loc_start : STR := STR::create(lib) + lib.Minus_Sign.char + lib.Minus_Sign.char ;
if void(fyle) or fyle.error then
SYS_ERROR::blind_error(self,file_path.str,LIBCHARS::default)
end ;
cursor : STR_CURSOR := fyle.fstr.str.cursor ;
fyle.close ; -- Finished with the file!
loop -- for each line in the file
index : STR_CURSOR ;
first : STR ;
second : STR ;
loop
if cursor.is_done then
return
end ;
line : STR := cursor.get_str.strip ; -- no line end!
if line.size > 0 then
index := line.cursor ;
index.set_comment_start(loc_start) ;
index.skip_space ;
if ~index.is_done then
break!
end
end
end ;
first := index.get_word ;
index.skip_space ;
if index.is_done then
second := void
else
second := index.get_word
end ;
if void(second) then -- another resource file name
loc_path : FILE_PATH := lib_head.append(first) ;
search_file(loc_path)
else -- a real map entry
tmp : FILE_PATH := lib_head.append(second) ;
class_map := class_map.insert(first,tmp)
end
end
end ;
create( cult : CULTURE ) : SAME
pre ~void(cult)
post (result.class_map.size > 0)
is
-- This routine enables a program to establish a particular culture for
-- some purpose which it desires from the standard culture.
if cult.state > cult.Collating then return cult.resources; end; -- already exists!
me : SAME := new ; me.lib := cult.sather_lib ;
res_file : FILE_PATH ;
lib_path : SEARCH_PATH := SEARCH_PATH::env_path(me.Lib_Res_ref) ; --SATHER_RESOURCES
if void(lib_path) then -- try default bin path head!
res_file := cult.resource_path.append(me.Leaf_Name_ref) ; -- sather_resources/lib_les
me.search_file(res_file)
else -- Use env path SATHER_RESOURCES.
loop
res_file := lib_path.elt!.append(me.Leaf_Name_ref) ;
me.search_file(res_file)
end
end ;
if void(me.class_map) or (me.class_map.size = 0) then -- haven't found a thing!
SYS_ERROR::blind_error(me,res_file.str,LIBCHARS::default)
end ;
return me
end ;
private initialise : SAME
pre true
post ~void(result)
is
-- This initialisation routine creates the default resource map and
-- then returns it.
res : SAME := create(CULTURE::default) ;
priv_default := res ;
return res
end ;
default : SAME
pre true
post ~void(result)
is
-- This routine creates the default resource as determined by the
-- current operating system cultural specification if necessary, otherwise
-- establishing a new default and returning it.
if void(priv_default) then
return initialise
else
return priv_default
end
end ;
private do_specials( loc_cursor : STR_CURSOR, out msg : STR) : BOOL
pre ~void(loc_cursor)
post ~void(msg) or ~result
is
-- This routine returns true if and only if it has been possible to make
-- up a message from one logical line (ie omitting blanks and comments and
-- merging escaped line ends) in the source.
res : FSTR ;
loc_cursor.skip_space ;
loc_cursor := loc_cursor.skip_to(lib.Colon.char) ;
if loc_cursor.is_done then return false; -- missing colon!
else loc_cursor.advance; -- past the colon!
end ;
if loc_cursor.is_done then msg := STR::create ; return true
else res := FSTR::create(loc_cursor.get_str) ;
end ;
loc_cursor := res.str.cursor ; -- to check for specials
escaped_tab : CHAR := CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_T.card,lib).char ;
escaped_lmark : CHAR := CHAR_CODE::create(UNICODE::LATIN_SMALL_LETTER_N.card,lib).char ;
loc_tab : CHAR := CHAR::create(CONTROL_CODES::HORIZONTAL_TAB,lib) ;
lmark : STR := lib.Line_Mark.tgt_str ;
clean : FSTR := FSTR::create ;
loop -- actually looking for specials!
if loc_cursor.is_done then break!; end ;
if loc_cursor.item = lib.Escape.char then
loc_cursor.advance ;
ch : CHAR := loc_cursor.get_item ;
if ch = escaped_tab then
clean := clean + loc_tab
elsif ch = escaped_lmark then
clean := clean + lmark
else
clean := clean + ch
end
else
clean := clean + loc_cursor.get_item
end
end ;
msg := clean.str ;
return true
end ;
private priv_read( class_name : RUNES, cnt : CARD ) : ARRAY{STR}
pre ~void(class_name)
post void(result) or (result.size >= cnt)
is
-- This routine returns a new array of strings in the current character
-- encoding and repertoire for the class name given. If the class is unknown
-- then an exception is raised!
--
-- Note that the special case of open-ended name lists is handled by
-- setting the count to zero - meaning that it has to be retrieved from
-- the file - assuming, since it was written to the file by this library,
-- that the value is correct!
--#OUT+"resources.sa priv_read 1: class:"+class_name.str+"\n";
loc_class_name : STR := UTF7::create(class_name).tgt_str ;
--#OUT+"priv_read 1. class_name="+class_name.str+", loc_class_name="+loc_class_name+"\n";#OUT.flush;
loc_path : FILE_PATH := class_map.get(loc_class_name) ;
--#OUT+"priv_read 1.1 class_map="+class_map.inspect+"\n"; #OUT.flush;
--#OUT+"resources.sa priv_read 2"+"\n";
loc_cnt : CARD := cnt ;
loc_start : STR := STR::create(lib) + lib.Hyphen.char + lib.Hyphen.char ;
--#OUT+"resources.sa priv_read 3"+"\n";
raiser : SYS_ERROR := SYS_ERROR::create ;
if void(loc_path) then -- resource file not identified!
raise "Resource_Missing. class_name="+class_name.str+"\n";
-- raiser.error(self,SYS_EXCEPT::Resource_Missing,class_name.str)
-- Don't use above, because of resouce error.
end ;
--#OUT+"resources.sa priv_read 4: loc_path:"+loc_path.str+"\n";
fyle : TEXT_FILE := TEXT_FILE::open_for_read(loc_path.str) ;
--#OUT+"resources.sa priv_read 4.1"+"\n";
if void(fyle) then
--#OUT+"resources.sa priv_read 4.2"+"\n";
raiser.error(self,SYS_EXCEPT::Bad_Name,loc_path.str)
elsif fyle.error then -- couldn't find the file?
--#OUT+"resources.sa priv_read 4.3"+"\n";
raiser.file_error(self,fyle)
end ;
--#OUT+"resources.sa priv_read 5"+"\n";
resource : SOURCE := SOURCE::create(fyle,loc_path) ;
count : CARD ;
loc_str : STR ;
resource.comment(loc_start) ;
resource.escape(lib.Escape.char) ;
index : STR_CURSOR := resource.line ;
--#OUT+"resources.sa priv_read 6"+"\n";
if index.item.is_digit then count := index.card
else
loc_str := index.get_word +
lib.Space.char + lib.Hyphen.char + lib.Space.char +
loc_path.str + lib.Space.char + lib.Left_Parenthesis.char +
loc_class_name + lib.Right_Parenthesis.char ;
raiser.error(self,SYS_EXCEPT::Bad_Value,loc_str)
end ;
--#OUT+"resources.sa priv_read 7 count="+count.str+"\n";
if loc_cnt = 0 then loc_cnt := count; end; -- handle the special case
if count = loc_cnt then
-- At least the first thing is OK
res : ARRAY{STR} := ARRAY{STR}::create(count) ;
arr_index : CARD := 0 ;
loop
count.times! ;
if do_specials(resource.line!,out res[arr_index]) then
arr_index := arr_index + 1;
else
--#OUT+"resources.sa priv_read 7.arr:"+arr_index.str+":"+count.str+"\n";
end
end ;
--#OUT+"resources.sa priv_read 8 class="+loc_class_name+", count="+arr_index.str+":"+count.str+"\n";
if arr_index = count then
--#OUT+"resources.sa priv_read 8.1 "+"\n";
--#OUT+"resources.sa priv_read 8.1.1 "+(void(res)or(res.size>=cnt)).str+"\n";
return res;
else
--#OUT+"resources.sa priv_read 8.2 "+"\n";
--#OUT+"resources.sa priv_read 8.3 loc_path:"+loc_path.str+"\n";
loc_str := arr_index.str +
lib.Space.char + lib.Hyphen.char + lib.Space.char +
loc_path.str + lib.Space.char + lib.Left_Parenthesis.char +
loc_class_name + lib.Right_Parenthesis.char ;
raiser.error(self,SYS_EXCEPT::Bad_Value,loc_str) ;
return void -- to keep compiler happy!
end
else
-- File is incorrect!
--#OUT+"resources.sa priv_read 9"+"\n";
loc_str := count.str + lib.Left_Angle.char + lib.Right_Angle.char +
loc_cnt.str + lib.Space.char + lib.Hyphen.char + lib.Space.char +
loc_path.str + lib.Space.char + lib.Left_Parenthesis.char +
loc_class_name + lib.Right_Parenthesis.char ;
--#OUT+"resources.sa priv_read 9.1"+"\n";
raiser.error(self,SYS_EXCEPT::Bad_Value,loc_str) ;
return void; -- to keep compiler happy!
end
end ;
read( class_name : RUNES, cnt : CARD ) : ARRAY{STR}
pre ~void(class_name)
post void(result) or (result.size >= cnt)
is
-- If self is void then this routine returns a new array of strings in
-- the run-time default character encoding and repertoire for the class name given.
-- If the appropriate message file cannot be found then an exception is raised.
res : SAME ;
if void(self) then res:= default ; else res:= self; end ;
return res.priv_read(class_name,cnt);
end ;
end ; -- RESOURCES