english version "1.0" identify "wxyz" #: Copyright (c) 1995, 1996, 2002 by Wayne C. Gramlich. #, All rights reserved. #, #, Permission to use, copy, modify, distribute, and sell this software #, for any purpose is hereby granted without fee provided that the above #, copyright notice and this permission are retained. The author makes #, no representations about the suitability of this software for any purpose. #, It is provided "as is" without express or implied warranty. module delta #: This module implements the delta object for SVMS. import address character chunk data_io errors format history in_stream integer logical manage out_stream project resources string svms unsigned vector version define delta #: A history file in memory record ancestor delta #: Ancestor delta (or ?? if first) history history #: Parent {history} object merge delta #: Merge delta (or ?? if none) number unsigned #: Delta number (never changes w/merge) offset unsigned #: Offset number (changes w/merge) project_name project_name #: {project_name} name for {delta} resources resources #: {resources} {delta} allocated from symbolic_link string #: Sym. link value (if {type} = {link}) timestamp unsigned #: Time delta showed up in project type delta_type #: Delta type user_name string #: User name version version #: {version} obj. (if {type} = {file}) generate address_get, allocate, erase, identical, print define delta_type #: Delta type enumeration deleted #: Deleted file directory #: Directory file #: File link #: Symbolic link generate equal, print #: {delta} procedures: procedure xallocate@delta takes history history type delta_type project_name project_name timestamp unsigned user_name string returns delta #: This procedure will allocate and return a new {delta} object #, from {history} with a type of {type}, a project of {project}, #, a timestamp of {timestamp}, and a user name of {user_name}. #: Carefully reinitialize {delta}: assert history !== ?? resources :@= history.resources assert resources !== ?? delta :@= delta_allocate@(resources) erase@(delta) delta_user_name :@= string_allocate@(resources) string_append@(delta_user_name, user_name) delta.ancestor := ?? delta.history := history delta.number := 0 delta.merge := ?? delta.offset := 0xffffffff delta.project_name := project_name delta.resources := resources delta.symbolic_link := string_allocate@(resources) delta.timestamp := timestamp delta.type := type delta.user_name := delta_user_name delta.version := ?? #debug_stream :@= delta.resources.global.debug_stream #format@format2[address, address](debug_stream, # 'allocate@delta()=>%X% (symlnk=%X%)\n\', # delta.address, delta.symbolic_link.address) return delta procedure compare@delta takes delta1 delta delta2 delta returns integer #: This procedure will return -1, 0, 1 depending upon whether {delta1} #, less than, equal to, or greater than {delta2}. assert delta1 !== ?? assert delta2 !== ?? zero :@= integer_convert@(0) result :@= compare@(delta1.timestamp, delta2.timestamp) if result = zero result := compare@(delta1.number, delta2.number) #debug_stream :@= delta1.resources.global.debug_stream #format@format7[address, unsigned, unsigned, address, unsigned, unsigned, # integer](debug_stream, # 'compare@delta(%X%:%d%:%d%, %X%:%d%:%d%) => %d%\n\', # delta1.address, delta1.timestamp, delta1.number, # delta1.address, delta2.timestamp, delta2.number, result) return result procedure deallocate@delta takes delta delta returns_nothing #: This procedure will deallocate {delta} and make it available for #, subsequent reallocation: #debug_stream :@= delta.resources.global.debug_stream #format@format2[address, address](debug_stream, # 'deallocate@delta()=>%X% (symlnk=%X%)\n\', # delta.address, delta.symbolic_link.address) assert delta !== ?? resources :@= delta.resources string_deallocate@(resources, delta.symbolic_link) string_deallocate@(resources, delta.user_name) erase@(delta) delta.resources := resources delta_deallocate@(resources, delta) procedure deleted_allocate@delta takes history history project_name project_name timestamp unsigned user_name string returns delta #: This procedure will create and append a new directory {delta} #, object for {history} with a project name of {project_name}, a timestamp #, of {timestamp}, and a user name of {user_name}. assert history !== ?? delta :@= xallocate@delta(history, directory, project_name, timestamp, user_name) return delta procedure delta_allocate@delta takes version version project_name project_name timestamp unsigned user_name string ancestor delta merge delta returns delta #: This procedure will allocate and return a new {delta} object for #, {version} with a project name of {project_name}, a timestamp of #, {timestamp}, a number of {number}, and a user name of {user_name}. history :@= version.history delta :@= xallocate@delta(history, file, project_name, timestamp, user_name) delta.version := version delta.ancestor := ancestor delta.merge := merge number :@= 0 if ancestor !== ?? number := ancestor.number + 1 if merge !== ?? merge_number :@= merge.number + 1 if merge_number > number number := merge_number delta.number := number number_manage@(version, number) return delta procedure directory_allocate@delta takes history history project_name project_name timestamp unsigned user_name string returns delta #: This procedure will create and return a new {delta} object for #, {history} with a project name of {project_name}, a timestamp of #, {timestamp}, and a user name of {user_name}. assert history !== ?? delta :@= xallocate@delta(history, directory, project_name, timestamp, user_name) return delta procedure read@delta takes data_in_stream data_in_stream history history returns delta #: This procedure will read in a {delta} object from {data_in_stream} #, and return it. assert history !== ?? buffer :@= data_in_stream.buffer resources :@= data_in_stream.resources delta_offset :@= unsigned_read@(data_in_stream) # Delta offset version_offset :@= unsigned_read@(data_in_stream) # Vers. offset trim@(buffer, 0) # Type string_read@(data_in_stream, buffer) delta_type:: delta_type := ?? if buffer = "Deleted" delta_type := deleted else_if buffer = "Directory" delta_type := directory else_if buffer = "File" delta_type := file else_if buffer = "Link" delta_type := link else assert false project_name :@= read@project_name(data_in_stream) # Project_Name timestamp :@= timestamp_read@(data_in_stream) # Timestamp number :@= unsigned_read@(data_in_stream) # Delta number trim@(buffer, 0) # User name string_read@(data_in_stream, buffer) version:: version := ?? delta :@= xallocate@delta(history, delta_type, project_name, timestamp, buffer) delta.offset := 0xffffffff delta.number := number switch delta_type case deleted, directory delta :@= delta #FIXME: do_nothing case file version :@= history.versions[version_offset] number_manage@(version, number) deltas :@= history.deltas deltas_size :@= deltas.size assert delta_offset = deltas_size if logical_read@(data_in_stream) ancestor_offset :@= unsigned_read@(data_in_stream) assert ancestor_offset < delta_offset delta.ancestor := deltas[ancestor_offset] if logical_read@(data_in_stream) merge_offset :@= unsigned_read@(data_in_stream) assert merge_offset < delta_offset delta.merge := deltas[merge_offset] case link string_read@(data_in_stream, delta.symbolic_link) default assert false delta.version := version new_line_read@(data_in_stream) return delta procedure string_append@delta takes delta delta text string returns_nothing #: This procedure will append the contents of {delta} to the end #, of {delta}. string_append@(delta.version, text) procedure write@delta takes delta delta data_out_stream data_out_stream returns_nothing #: This procedure will write {delta} out to {data_out_stream}. assert delta !== ?? assert data_out_stream !== ?? debug_stream :@= data_out_stream.resources.global.debug_stream tag_write@(data_out_stream, "X"[0]) delta_offset :@= delta.offset unsigned_write@(data_out_stream, delta_offset) # Delta offset unsigned_write@(data_out_stream, delta.version.offset) # Vers. offset switch delta.type # Type case deleted string_write@(data_out_stream, "Deleted") case directory string_write@(data_out_stream, "Directory") case file string_write@(data_out_stream, "File") case link string_write@(data_out_stream, "Link") default assert false write@(delta.project_name, data_out_stream) # Project_Name timestamp_write@(data_out_stream, delta.timestamp) # Timestamp unsigned_write@(data_out_stream, delta.number) # Number string_write@(data_out_stream, delta.user_name) # User name # Write the type specific portions of the {delta}: switch delta.type case deleted, directory delta := delta #FIXME: do_nothing case file ancestor :@= delta.ancestor if ancestor == ?? logical_write@(data_out_stream, false) else logical_write@(data_out_stream, true) ancestor_offset :@= ancestor.offset if ancestor_offset >= delta_offset format@format2[unsigned, unsigned](debug_stream, 'Ancestor offset=%d% < delta_offset=%d%\n\', ancestor_offset, delta_offset) assert false unsigned_write@(data_out_stream, ancestor_offset) merge :@= delta.merge if merge == ?? logical_write@(data_out_stream, false) else logical_write@(data_out_stream, true) merge_offset :@= merge.offset assert merge_offset < delta_offset unsigned_write@(data_out_stream, merge_offset) case link string_write@(data_out_stream, delta.symbolic_link) new_line_write@(data_out_stream)