english version "1.0" identify "xyz" #: Copyright (c) 1995, 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 misc #: This module implements the miscellaneous functions for SVMS. import address character chunk data_io file_name file_system format in_stream logical manage out_stream project set string svms unsigned vector version #: Miscellaneous procedures: procedure paragraph_prompt@in_stream takes in_stream in_stream out_stream out_stream prompt string result string returns_nothing #: This procedure will prompt the user for a paragraph of text #, terminated by a blank line. The text is read from {in_stream} #, appended to {result}. Each line of text is prompted by outputing #, {prompt} to {out_stream}. line_feed :@= "\n\"[0] character :@= line_feed loop if character = line_feed put@(prompt, out_stream) flush@(out_stream) previous_character :@= character character :@= character_get@(in_stream) until character = line_feed && previous_character = line_feed character_append@(result, character) procedure timestamp_append@string takes buffer string date unsigned returns_nothing #: This procedure will convert "date" into a string of the form #, 'YYYY/MM/DD@hh:mm:ssGMT' and append it to {buffer}. # Deal with year: original_date :@= date days :@= date / 86400 # 86400 = seconds per day date :@= date % 86400 original_days :@= days year :@= 1970 loop year_days :@= (year % 4 = 0) ? 366 : 365 while days >= year_days days :-= year_days year :+= 1 # Deal with month: foo :@= days month :@= 1 month_days :@= 0 zero :@= "0"[0] one :@= "1"[0] loop tag :@= ".1x1010110101"[month] if tag = zero month_days := 30 else_if tag = one month_days := 31 else assert month = 2 month_days := (year % 4 = 0) ? 29 : 28 while days >= month_days days :-= month_days month :+= 1 # Deal with day, hour, minutes, seconds: day :@= days + 1 hours :@= date / 3600 # 3600 = seconds per hour date :%= 3600 minutes :@= date / 60 # 60 = seconds per minute date :%= 60 seconds :@= date # Output the date and time: at :@= "@"[0] colon :@= ":"[0] slash :@= "/"[0] unsigned_fixed_append@(buffer, year, 4) character_append@(buffer, slash) unsigned_fixed_append@(buffer, month, 2) character_append@(buffer, slash) unsigned_fixed_append@(buffer, day, 2) character_append@(buffer, at) unsigned_fixed_append@(buffer, hours, 2) character_append@(buffer, colon) unsigned_fixed_append@(buffer, minutes, 2) character_append@(buffer, colon) unsigned_fixed_append@(buffer, seconds, 2) string_append@(buffer, "GMT") procedure timestamp_lop@string takes buffer string returns unsigned #: This procedure will return a timestamp read from {buffer}. # Read in the timestamp data: colon :@= ":"[0] slash :@= "/"[0] year :@= unsigned_fixed_lop@(buffer, 4) assert character_lop@(buffer) = slash month :@= unsigned_fixed_lop@(buffer, 2) assert character_lop@(buffer) = slash day :@= unsigned_fixed_lop@(buffer, 2) assert character_lop@(buffer) = "@"[0] hours :@= unsigned_fixed_lop@(buffer, 2) assert character_lop@(buffer) = colon minutes :@= unsigned_fixed_lop@(buffer, 2) assert character_lop@(buffer) = colon seconds :@= unsigned_fixed_lop@(buffer, 2) assert character_lop@(buffer) = "G"[0] assert character_lop@(buffer) = "M"[0] assert character_lop@(buffer) = "T"[0] # Convert all of these numbers into a timestamp: # Deal with year: days :@= 0 index :@= 1970 loop while index < year days :+= (index % 4 = 0) ? 366 : 365 # 365 = days/yr. & 366=leap yr. index :+= 1 # Deal with month: zero :@= "0"[0] one :@= "1"[0] index :@= 1 loop while index < month tag :@= ".1x1010110101"[index] if tag = zero days :+= 30 else_if tag = one days :+= 31 else assert index = 2 days :+= (year % 4 = 0) ? 29 : 28 index :+= 1 days :+= day - 1 # Build the final timestamp: timestamp :@= days * 86400 # 86400 = seconds in a day timestamp :+= hours * 3600 # 3600 = seconds in an hour timestamp :+= minutes * 60 # 60 = seconds in a minute timestamp :+= seconds return timestamp procedure number_append@string takes buffer string number unsigned returns_nothing #: This procedure will append {number} to {buffer} as a decimal number. if number >= 10 number_append@(buffer, number / 10) # 48 = unsigned_convert@("0"[0]) character_append@(buffer, character_convert@(48 + number % 10)) procedure unsigned_fixed_append@string takes buffer string number unsigned width unsigned returns_nothing #: This procedure will append {number} out to {buffer} as {width} #, digit decimal number. if width > 1 unsigned_fixed_append@(buffer, number / 10, width - 1) # 48 = unsigned_convert@("0"[0]) character_append@(buffer, character_convert@(48 + number % 10)) procedure unsigned_fixed_lop@string takes buffer string width unsigned returns unsigned #: This procedure will lop a {width} digit decimal number from {buffer} #, and return it. number :@= 0 loop while width != 0 digit :@= character_lop@(buffer) assert is_digit@(digit) # 48 = unsigned_convert@("0"[0]) number := number * 10 + unsigned_convert@(digit) - 48 width :-= 1 return number procedure log10@unsigned takes number unsigned returns unsigned #: This routine will return the number of digits needed to represent #, {number}; thus, the number 0 on input returns 1. if number < 10 return 1 if number < 100 return 2 if number < 1000 return 3 if number < 10000 return 4 if number < 100000 return 5 if number < 1000000 return 6 if number < 10000000 return 7 if number < 100000000 return 8 if number < 1000000000 # 1,000,000,000 return 9 # {unsigned} is a 32-bit number between 0 and 2*32-1 (4,294,967,295). #, So, 10 is the biggest number that can be returned. return 10