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