Trailing-Edge
-
PDP-10 Archives
-
BB-R775C-BM
-
sources/dixstr.bli
There are 21 other files named dixstr.bli in the archive. Click here to see a list.
%TITLE 'DIXSTR -- String Conversion Module'
MODULE dixstr
! COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1983, 1985.
! ALL RIGHTS RESERVED.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND
! COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
! THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR
! ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
! AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE
! SOFTWARE IS HEREBY TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
! NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
! EQUIPMENT CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF
! ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
!++
! .chapter >DIXSTR
!
! The module DIXSTR contains the string conversion routines.
!
! FACILITY: Data Conversion Routines (DIX)
!
! ABSTRACT: String conversion routines and related data
!
! ENVIRONMENT:
!
! AUTHOR: David Dyer-Bennet, Creation Date: 11-Feb-82
!--
( !
IDENT = '2.0(50)' ! \.p;\
! **EDIT**
%REQUIRE ('DIXSWI.REQ') ! [%O'34']
%BLISS36 (
, ENTRY ( ! ; .P;Entry names:
dixstr ! \
)
)
) =
BEGIN
!++
! .hl 1 Require files
!--
REQUIRE 'DIXREQ.REQ'; ! \
!++
! .hl 1 Library files
!--
LIBRARY 'DIXCST'; ! \
%sbttl 'Edit History' ! [7] Add this entire subsection
!++
! .hl 1 Edit History
!--
LIBRARY 'VERSION';
! ; .autotable
!++ COPY
new_version (1, 0)
edit (7, '23-Aug-82', 'David Dyer-Bennet')
%( Change version and revision standards everywhere.
Files: All. )%
edit (10, '22-Sep-82', 'David Dyer-Bennet')
%( Always use long_relative addressing on VAX. )%
Edit (%O'30', '19-Jan-83', 'David Dyer-Bennet')
%( Update copyright notices, add mark at end of edit histories.
)%
Edit (%O'34', '19-May-83', 'David Dyer-Bennet')
%( Add DIXSWI require file to headings of all modules. DIXSWI
contains the BLISS32 addressing-mode declarations and the TOPS-10
OTS declaration to avoid invoking the losing default of .REQUESTING
the OTS library from whatever directory the compiler was called from
when the build ran.
)%
Edit (%O'35', '7-June-83', 'Charlotte L. Richardson')
%( Declare version 1 complete. All modules.
)%
new_version (1, 1)
new_version (2, 0)
Edit (%O'36', '11-Apr-84', 'Sandy Clemens')
%( Put all Version 2 DIX development files under edit control. Some of
the files listed below have major code edits, or are new modules. Others
have relatively minor changes, such as cleaning up a comment.
FILES: COMDIX.VAX-COM, COMPDX.CTL, DIXCST.BLI, DIXDEB.BLI,
DIXDN.BLI (NEW), DIXFBN.BLI, DIXFP.BLI, DIXGBL.BLI, DIXGEN.BLI,
DIXHST.BLI, DIXINT.PR1, DIXINT.PR2, DIXLIB.BLI, DIXPD.BLI (NEW),
DIXREQ.REQ, DIXSTR.BLI, DIXUTL.BLI, DXCM10.10-CTL, MAKDIXMSG.BLI,
STAR36.BLI, VERSION.REQ.
)%
Edit (%O'50', '8-Oct-84', 'Sandy Clemens')
%( Add new format of COPYRIGHT notice. FILES: ALL )%
! **EDIT**
!-- .autoparagraph
mark_versions ('DIX')
!++
! .hl 1 Debugging Declarations
!--
UNDECLARE %QUOTE $descriptor; !\.p;\Something leaves this around....
dix$module_debug (off)
!++
! .hl 1 Own storage
!--
! [7] Remove version number word
! [7] Add dixcst library version number word
OWN ! [7]
dix$g_dixcst_version: INITIAL (dix$k_dixcst_version); ! [7]
!
! ; .hl 2 CST's
! ; Expand the information from DIXCST into the necessary CST entries
! ; for each character set:
!
build_cst ('ascii') ! ; ASCII,
build_cst ('sixbit') ! ; SIXBIT, and
build_cst ('ebcdic') ! ; EBCDIC.
%SBTTL 'String data-type table extension (dix$adttx_st)'
!++
! .hl 2 >dix$adttx_st
! The dix$adttx_st is an extension of the basic dix$adtt_st. They would be one
! table, but combining them would cause loading problems if the string
! conversion routines are not loaded. The common module will make references
! to the dix$adtt_st, so it cannot be pulled out and added to this. So it
! got segmented. Soitgoes.
!
! The dix$adttx_st contains the maximum value for a character of the specified
! type, and the address of the cst to use in converting to/from that type.
!
! Here's the exact dttx definition:
! .s1
! .literal
!--
!++ copy
$field
stdx_fields =
SET
stdx$v_max_char = [$byte], ! Maximum character value
stdx$v_cst_max = [$byte], ! Maximum table index
stdx$v_cst_addr = [$address], ! Address of cst
stdx$v_fill_char = [$bits(8)], ! Widest character set so far is 8
stdx$v_sub_for_invalid = [$bits(8)]
TES;
LITERAL
stdx$k_size = $field_set_size;
!-- .end literal
MACRO
decl_string_item ! \.P;Macro >\ =
(class_code, item_name, short_name, type_code,
byt_size, sys_orig, lng_spec, char_set_name, fill_char,
sub_for_invalid) =
!++
! this local definition will be used when dt_class_string_def is
! expanded. It selects the items we care about from the full set of
! information stored in DIXLIB and generates PRESET items to initialize
! the table.
!--
[type_code, stdx$v_max_char] = %NAME ('cst$k_', char_set_name, '_max'),
[type_code, stdx$v_cst_max] = MAX (
%NAME ('cst$k_', char_set_name, '_max'), !
%NAME ('cst$k_', char_set_name, '_si_max') !
), !
[type_code, stdx$v_cst_addr] = %NAME ('dix$acst_', char_set_name),
[type_code, stdx$v_fill_char] = fill_char,
[type_code, stdx$v_sub_for_invalid] = sub_for_invalid,
%;
OWN
dix$adttx_st : BLOCKVECTOR [dt_class_string_max + 1, stdx$k_size] !
FIELD (stdx_fields) !
PSECT (readonly_psect) ! \.p;Assign dix$adttx_st to \.
PRESET ( ! Begin PRESET
dt_class_string_def ! Pull our info from master table
[0, stdx$v_cst_addr] = 0 ! Previous macro leaves trailing ","
); ! End PRESET
%SBTTL 'External References'
!++
! .hl 1 External references
!--
EXTERNAL ! \.p;\:
!++ copy /strip
dix$adtt_st : dtt_st;
!--
EXTERNAL ROUTINE ! \.p;\:
! ; .list 0, "o"
!++ copy /strip .le;
dix$$fetch_bits,
dix$$stuff_bits : NOVALUE,
dix$$incr_des : NOVALUE,
dix$$copy_structure : NOVALUE,
dil$$usr_intrfc_hand,
dix$$port_hand,
dix$$check_ffd : NOVALUE;
!-- .end list
%SBTTL 'GLOBAL ROUTINE dix$$con_str'
GLOBAL ROUTINE dix$$con_str ! \.!=;.hl 1 \
! ; .index dix$$con_str
!++
! Portal For String Conversions.
!
! SCH: Level = 1, DD = 2. Pseudonym >dixstr>.
!
! Algorithm: Convert string to an 8-bit intermediate form (note: thus
! we cannot handle character sets with more than 256 distinct
! characters). Convert the intermediate form to the destination
! character set. Use conversion tables for both directions (thus it's
! very easy to add additional character sets, or to change conversions).
! Strings longer than some threshold value will be converted in chunks
! (thus it is implicit in our definition of string that there is not
! interaction between characters).
!
! For first release, chunk size will be 1. This makes for easiest
! system independence. If performance becomes a problem and it is found
! feasible to format the conversion tables for use by optimized string
! conversion instructions on various systems, then this could be done.
!
! The size of the intermediate bytes, 8 bits, is not a crucial design
! feature. The main effect of increasing it would most likely be a
! moderate decrease in performance, especially on VAX systems. It will
! be a compile-time parameter of the source code. Thus, no problem is
! anticipated if it becomes necessary to support a character set
! containing more than 256 characters.
!
! No error checking is performed on the descriptor; this is an
! internal routine, and it is the duty of the calling routines to do the
! necessary checking (remember that, in many cases, the descriptor will
! just have been put together by the caller).
!
! Routine value: Status Value, one of the following:
! .s 1.list 1, "o"
! .le;dix$_invalchar
! .le;dix$_graphic
! .le;dix$_fmtlost
! .le;dix$_nonprint
! .le;dix$_trunc
! .end list
!
! Formal arguments:
!--
( ! ; .s 1.list 1
src_ffd, ! \.le;\: Address of FFD describing source field
dst_ffd ! \.le;\: Address of FFD describing destination field
) = ! ; .end list
BEGIN ! Begin dix$$con_str
MAP
src_ffd : REF forgn_descr,
dst_ffd : REF forgn_descr;
$field
flg_fields =
SET
flg$v_invalid = [$bit],
flg$v_graphic = [$bit],
flg$v_format = [$bit],
flg$v_noprint = [$bit],
flg$v_trunc = [$bit],
flg$v_src_done = [$bit]
TES;
LITERAL
flg$k_size = $field_set_size;
LOCAL
error_temp: VOLATILE,
src_char,
dst_char,
si_char,
src_tbl,
dst_tbl,
char_cnt,
src_char_cnt, ! Must init to 0
dst_char_cnt, ! Must init to 0
flags : BLOCK [flg$k_size] FIELD (flg_fields), ! Must init to 0
src_pnt : forgn_descr, ! "Pointer" to be incremented
dst_pnt : forgn_descr; ! "Pointer" to be incremented
ENABLE dix$$port_hand (error_temp); ! \.p;
ROUTINE get_src_si ! \.!=;.hl 2 \ (local)
! ; .index get_src_si (local)
!++
! Local to dix$$con_str.
!
! This routine attempts to get the next character from the source.
! The SI for that character is returned as the routine value, if a
! character is found. The various flags in the flag word are updated.
! In particular, the src_done flag is set if no character is returned.
!
! The source pointer is incremented if a character is found and returned.
! Note that this means that the address of the character after the last
! one in a counted string must be a valid address (it need not be
! actually readable).
!
! SCH: Level = 2
!
! Routine value: String Intermediate (SI) form of character found, or
! si$k_invalid if an invalid source character found, or 0 if nothing found
! (in this case, the end-of-source flag should be set).
!
! Formal Arguments:
!--
( ! ; .s 1.list 1
src_pnt, ! \.le;\: Address of modifiable source FFD
! ; (the FFD is modified)
src_tbl, ! \.le;\: Address of source CST
char_cnt, ! \.le;\: Adr of count of src chars used
! ; (incremented)
flags ! \.le;\: Address of flag word
! ; (the flags are modified)
) = ! ; .end list
BEGIN ! Routine get_src_si
MAP
src_pnt: REF forgn_descr,
src_tbl: REF cst (0), ! Actual size is irrelevant
flags: REF BLOCK [flg$k_size] FIELD (flg_fields);
LOCAL
src_char,
char_found, ! Set if a character from src is being returned
! Must init to 0
si_char;
char_found = 0; ! Initialize local variable
CASE .dix$adtt_st [.src_pnt [ffd$v_dt_type], std$v_lng_indic] FROM 1 TO std$k_max_lng_indic OF
SET
[std$k_lng_spec] :
!
! Length of src field is explicitly specified
!
BEGIN ! CASE: std$k_lng_spec
IF ..char_cnt LSS .src_pnt [ffd$v_length]
THEN
BEGIN ! IF .char_cnt LSS .src_pnt [ffd$v_length]
char_found = 1; ! Something was really found
src_char = dix$$fetch_bits (.src_pnt [ffd$v_unit], .src_pnt [ffd$v_offset],
.dix$adtt_st [.src_pnt [ffd$v_dt_type], std$v_byt_siz]);
END ! IF .char_cnt LSS .src_pnt [ffd$v_length]
ELSE
flags [flg$v_src_done] = 1;
END; ! CASE: std$k_lng_spec
[std$k_lng_nul] :
!
! Source field is terminated by a trailing NUL
!
BEGIN ! CASE: std$k_lng_nul
src_char = dix$$fetch_bits (.src_pnt [ffd$v_unit], .src_pnt [ffd$v_offset],
.dix$adtt_st [.src_pnt [ffd$v_dt_type], std$v_byt_siz]);
IF .src_char EQL 0
THEN
flags [flg$v_src_done] = 1
ELSE
char_found = 1; ! Something was found
END; ! CASE: std$k_lng_nul
TES;
IF .char_found
THEN
BEGIN ! Character found
dix$$incr_des (.src_pnt);
.char_cnt = ..char_cnt + 1;
IF .src_char LEQ .dix$adttx_st [.src_pnt [ffd$v_dt_type], stdx$v_cst_max]
THEN
BEGIN ! Valid character found
flags [flg$v_noprint] = .flags [flg$v_noprint] OR !
.cst_ref (.src_tbl, .src_char, cst$v_to_si_noprint_err) ;
flags [flg$v_format] = .flags [flg$v_format] OR !
.cst_ref (.src_tbl, .src_char, cst$v_to_si_format_err) ;
flags [flg$v_graphic] = .flags [flg$v_graphic] OR !
.cst_ref (.src_tbl, .src_char, cst$v_to_si_graphic_err) ;
IF .cst_ref (.src_tbl, .src_char, cst$v_to_si_valid)
THEN ! CST entry is valid
.cst_ref (.src_tbl, .src_char, cst$v_to_si_char)
! SI char is routine value
ELSE
BEGIN ! CST entry is invalid
flags [flg$v_invalid] = 1;
si$k_invalid ! SI char means invalid conversion
END ! CST entry is invalid
END ! Valid character found
ELSE ! Invalid character found
BEGIN ! CST entry is nonexistent
flags [flg$v_invalid] = 1; !
si$k_invalid ! SI char means invalid conversion
END ! CST entry is nonexistent
END ! Character found
ELSE
0 ! No character found
END; ! Routine get_src_si
ROUTINE put_si_dst ! \.!=;.hl 2 \ (local)
! ; .index put_si_dst
!++
! This routine takes the given SI character code and puts the appropriate
! destination character code in the next position of the destination string
! pointed to by the pointer FFD given.
!
! The pointer FFD is updated if a character is put to the destination.
! This means that the address of the character AFTER any string must be
! valid, although it need not be accessible). If a character cannot be
! put to the destination (because the destination is too small) the
! truncation flag in the flag word is set.
!
! In the case of fields terminated with a terminating char, room is
! saved in the field for that character. This must be done because it
! is not possible to decrement a descriptor, and it is not acceptable to
! be unable to truncate a field, preserving the part that fits.
!
! SCH: Level = 2
!
! Routine value: None
!
! Formal Arguments:
!--
( ! ; .s 1.list 1
dst_pnt, ! \.le;\: Address of destination FFD
! ; (FFD is incremented)
dst_tbl, ! \.le;\: Address of destination CST
char_cnt, ! \.le;\: Address of num of chars put to dst
! ; (incremented)
flags, ! \.le;\: Address of flag word
! ; (flags are modified)
si_char ! \.le;\: SI code for char to put to dst
) : NOVALUE = ! ; .end list
BEGIN ! ROUTINE put_si_dst
MAP
dst_pnt: REF forgn_descr,
dst_tbl: REF cst (0), ! Real length doesn't matter
flags: REF BLOCK [flg$k_size] FIELD (flg_fields);
IF ..char_cnt GEQ
(CASE .dix$adtt_st [.dst_pnt [ffd$v_dt_type], std$v_lng_indic] FROM 1 TO std$k_max_lng_indic OF
SET
[std$k_lng_spec] :
!
! Length of src field is explicitly specified
!
.dst_pnt [ffd$v_length];
[std$k_lng_nul] :
!
! Source field is terminated by a trailing NUL
!
.dst_pnt [ffd$v_length] - 1;
TES )
THEN
flags [flg$v_trunc] = 1
ELSE
BEGIN
LOCAL
loc_si_char;
loc_si_char = (IF .si_char GTR .dix$adttx_st [.dst_pnt [ffd$v_dt_type], stdx$v_cst_max]
THEN
BEGIN
flags [flg$v_invalid] = 1;
si$k_invalid
END
ELSE
.si_char);
IF .cst_ref (.dst_tbl, .loc_si_char, cst$v_to_typ_valid)
THEN
BEGIN ! CST entry valid
dix$$stuff_bits (.dst_pnt [ffd$v_unit], .dst_pnt [ffd$v_offset],
.dix$adtt_st [.dst_pnt [ffd$v_dt_type], std$v_byt_siz], !
.cst_ref (.dst_tbl, .loc_si_char, cst$v_to_typ_char));
flags [flg$v_noprint] = .flags [flg$v_noprint] OR !
.cst_ref (.dst_tbl, .loc_si_char, cst$v_to_typ_noprint_err);
flags [flg$v_format] = .flags [flg$v_format] OR !
.cst_ref (.dst_tbl, .loc_si_char, cst$v_to_typ_format_err);
flags [flg$v_graphic] = .flags [flg$v_graphic] OR !
.cst_ref (.dst_tbl, .loc_si_char, cst$v_to_typ_graphic_err);
END ! CST entry valid
ELSE
BEGIN ! CST entry invalid
dix$$stuff_bits (.dst_pnt [ffd$v_unit], .dst_pnt [ffd$v_offset],
.dix$adtt_st [.dst_pnt [ffd$v_dt_type], std$v_byt_siz], !
.dix$adttx_st [.dst_pnt [ffd$v_dt_type], stdx$v_sub_for_invalid]);
flags [flg$v_invalid] = 1;
END; ! CST entry invalid
dix$$incr_des (.dst_pnt);
.char_cnt = ..char_cnt + 1
END;
END; ! ROUTINE put_si_dst
ROUTINE dst_cleanup ! \.!=;.hl 2 \ (local)
! ; .index dst_cleanup
!++
! Local to dix$$con_str.
!
! This routine does necessary tail end processing on an output string
! field (such as filling, placing of terminator characters).
!
! SCH: Level = 2
!
! Routine value: None
!
! Formal Arguments:
!--
( ! ; .s 1.list 1
dst_pnt, ! \.le;\: Address of destination FFD
! ; (FFD is incremented)
char_cnt, ! \.le;\: Character count
flags ! \.le;\: Address of flag word
) : NOVALUE = ! ; .end list
BEGIN ! ROUTINE dst_cleanup
MAP
dst_pnt: REF forgn_descr,
flags: REF BLOCK [flg$k_size] FIELD (flg_fields);
!++
! Since the terminator for terminated fields is stored in the "fill
! character" slot in the dttx, and since put_si_dst guarantees to save
! space for the terminator when necessary, all that is necessary to do
! is to fill any remaining space with fill characters.
!--
INCR local_cnt FROM .char_cnt + 1 TO .dst_pnt [ffd$v_length] DO
BEGIN ! INCR local_cnt
dix$$stuff_bits (.dst_pnt [ffd$v_unit], .dst_pnt [ffd$v_offset],
.dix$adtt_st [.dst_pnt [ffd$v_dt_type], std$v_byt_siz], !
.dix$adttx_st [.dst_pnt [ffd$v_dt_type], stdx$v_fill_char]);
dix$$incr_des (.dst_pnt)
END; ! INCR local_cnt
END; ! ROUTINE dst_cleanup
src_char_cnt = 0; ! Initialize local var
dst_char_cnt = 0; ! Initialize local var
BEGIN
LOCAL adr_pnt;
INCRA adr_pnt FROM flags TO flags + (flg$k_size - 1) * %UPVAL BY %UPVAL DO
.adr_pnt = 0 ! Initialize local var
END;
dix$$check_ffd (.src_ffd);
dix$$check_ffd (.dst_ffd);
dix$$copy_structure (.src_ffd, ffd$k_size, src_pnt);
dix$$copy_structure (.dst_ffd, ffd$k_size, dst_pnt);
src_tbl = .dix$adttx_st [.src_pnt [ffd$v_dt_type], stdx$v_cst_addr];
dst_tbl = .dix$adttx_st [.dst_pnt [ffd$v_dt_type], stdx$v_cst_addr];
!
WHILE 1 DO ! Loop until the EXITLOOP executes
BEGIN
si_char = get_src_si (src_pnt, .src_tbl, src_char_cnt, flags);
IF .flags [flg$v_src_done]
THEN
BEGIN
dst_cleanup (dst_pnt, .dst_char_cnt, flags);
EXITLOOP
END
ELSE
put_si_dst (dst_pnt, .dst_tbl, dst_char_cnt, flags, .si_char);
END;
!
! ; .hl 2 DIX$$CON_STR status values
! ; .p;In order of priority, tell the user what went wrong:
!
!++ copy /strip .i 5;
IF .flags [flg$v_invalid] THEN RETURN dix$_invalchar;
IF .flags [flg$v_graphic] THEN RETURN dix$_graphic;
IF .flags [flg$v_format] THEN RETURN dix$_fmtlost;
IF .flags [flg$v_noprint] THEN RETURN dix$_nonprint;
IF .flags [flg$v_trunc] THEN RETURN dix$_trunc;
RETURN dix$success_cond;
!--
END; ! End of dix$$con_str
END ! End MODULE dixstr
ELUDOM