Pastey 715.ex

-- convert numeric literals to enumerated types:
include std/regex.e 
include std/types.e 
include std/text.e 
include std/filesys.e 
include std/io.e 
include std/get.e 
include msgtext.e 
include needleinahaystack/key.e as key 
 
constant DEBUG_MSGTEXT = 0 
constant verbose = 1 
constant msgnumtext = regex:new(`\{(\s*)([0-9A-Z_]+), (["` & "`" & `]).*\3\s*\},$`) 
constant special_statement = regex:new(`(CompileErr|InternalErr|Warning)\(\s*([0-9]+),?`)-- regex:new(`(CompileErr|InternalErr|Warning)\([ ]*([0-9]+)`) 
constant false = 0 
constant true = 1 
integer number_of_files_changed = 0 
constant escaped = { "\\n", "\\t", "\\\"", "\\\'" } 
constant escapable = "\n\t\"'" 
function only_alphanumeric(sequence s) 
	sequence t = "" 
	for si = 1 to length(s) do 
		if t_alnum(s[si]) then 
			t = upper(append(t,s[si])) 
		elsif length(t) and t[$] != '_' then 
			t = append(t,'_') 
		end if 
	end for 
	if length(t) and t[$] = '_' then 
		t = t[1..$-1] 
	end if		 
	return t 
end function 
		 
function make_id( integer val ) 
	sequence t = GetMsgText(val) 
	t = t[10..$] 
	return "MSG_" & only_alphanumeric(t) 
end function 
 
function replace_literals(sequence path_name, sequence item) 
	boolean changed = false 
	object line 
	integer user_out 
	if verbose then 
		user_out = 1 
	else 
		ifdef UNIX then 
			user_out = open("/dev/null", "a", true) 
		elsedef 
			user_out = open("NUL", "a", true) 
		end ifdef 
		-- oops 
		if user_out = -1 then		 
			user_out = 1 
		end if 
	end if 
	if match(".bak", item[D_NAME]) then 
		return 0 
	end if 
	if not equal(fileext(item[D_NAME]),"e") then 
		return 0 
	end if 
	if equal("msgtext.e", item[D_NAME]) and not equal(fileext(item[D_NAME]),"e") then 
		return 0 
	end if 
	 
	delete_file(item[D_NAME] & ".bak") 
	while not copy_file(item[D_NAME], item[D_NAME] & ".bak") do 
		printf(user_out, "Trying to backup ... %s...\n", item[D_NAME..D_NAME] ) 
	end while 
	printf(user_out, "Processing %s...", item[D_NAME..D_NAME]) 
	integer ifd = open(item[D_NAME] & ".bak", "r") 
	integer ofd 
	while ofd = -1 entry do 
	entry 
		ofd = open(item[D_NAME], "w") 
	end while 
	while sequence(line) entry do 
		object fi 
		fi = regex:find( special_statement, line ) 
		if sequence(fi) then 
			sequence buffer = value(line[fi[3][1]..fi[3][2]])				 
			line = line[1..fi[3][1]-1] & make_id( buffer[2] ) & line[fi[3][2]+1..$] 
			changed = true 
		end if 
		puts(ofd, line) 
	entry 
		line = gets(ifd) 
	end while 
	close(ifd) 
	close(ofd) 
	if changed then 
		puts(user_out, "done.\n") 
		number_of_files_changed += 1 
		delete_file(item[filesys:D_NAME] & ".bak") 
	else 
		puts(user_out, "reverted.\n") 
		-- the file wasn't modified. 
		-- move backup back to preserve modification times 
		copy_file(item[D_NAME] & ".bak", item[D_NAME]) 
	end if 
	return 0 
end function 
 
 
function escape(sequence s) 
	sequence out = "" 
	for k = 1 to length(s) do 
		integer c = s[k] 
		sequence escedhaystack = escaped & { c } 
		sequence eschaystack = escapable & c 
		out &= escedhaystack[find(c,eschaystack)] 
	end for 
	return out 
end function 
 
 
procedure update_msgtext() 
	sequence list = {} 
	boolean fatal_error = false 
	if DEBUG_MSGTEXT or copy_file("msgtext.e","msgtext.bak") then 
		integer ofd 
		integer ifd 
		if DEBUG_MSGTEXT then 
			ofd = open("msgtext.out", "w") 
			ifd = open("msgtext.e", "r") 
		else 
			ifd = open("msgtext.bak", "r") 
			ofd = open("msgtext.e", "w") 
		end if 
		object line 
		boolean changed = false 
		sequence StdErrMsgs = "" 
		while sequence(line) and not eu:match( "constant StdErrMsgs = {", line ) entry do 
			puts(ofd, line) 
		entry 
			line = gets(ifd) 
		end while 
		object fi 
		sequence buffer 
		while sequence(line) and sequence(fi) and buffer[1] = GET_SUCCESS entry do 
			integer previous_location 
			sequence text = GetMsgText( buffer[2] ) 
			sequence new_id = make_id(buffer[2]) 
                        -- the following is like win32lib.ew w32findKey() but with more options. 
			previous_location = key:find(new_id, 2, 1, , list) 
			if previous_location then 
				if not equal(text[10..$],list[previous_location][3]) then 
					printf(2, "Error: Conflicting ids both map to %s one at %d.  The other at %d.\n", {new_id, list[previous_location][1], buffer[2]}) 
					fatal_error = true 
				else 
					printf(2, "Note: Duplicate symbol located at %d and %d.\n", {list[previous_location][1], buffer[2]}) 
				end if 
			else 
				list = append(list, {buffer[2], new_id, text[10..$]}) 
			end if 
		entry 
			line = gets(ifd) 
			fi = regex:find( msgnumtext, line ) 
			buffer = value(line[fi[3][1]..fi[3][2]]) 
		end while 
		puts(ofd, "export type enum msg_id\n") 
		printf(ofd, "\t%s = 0,\n", list[1][2..2]) 
		for k = 2 to length(list) do 
			printf(ofd, "\t%s,\n", list[k][2..2]) 
		end for 
		puts(ofd, "\t$\n") 
		puts(ofd, "end type\n") 
		puts(ofd, "constant StdErrMsgs = {\n") 
		for k = 1 to length(list) do 
			printf(ofd, "\t{%s, \n\t\t\"%s\"},\n\n", {list[k][2], escape(list[k][3])}) 
		end for 
		--puts(ofd, "\t$\n}\n") 
		while sequence(line) do 
			puts(ofd, line) 
			line = gets(ifd) 
		end while 
		close(ofd) 
		close(ifd) 
		if fatal_error then 
			abort(1) 
		end if 
	end if 
end procedure 
 
if file_exists("msgtext.bak") then 
	printf(2,"msgtext.bak exists... cannot continue.\n", {}) 
	abort(1) 
end if 
if not DEBUG_MSGTEXT then 
	walk_dir( current_dir(), routine_id("replace_literals") ) 
end if 
if DEBUG_MSGTEXT or number_of_files_changed then 
	update_msgtext() 
	number_of_files_changed += 1 
	printf(1,"%d files changed.\n", {number_of_files_changed}) 
end if

1. Comment by SDPringle Jan 02, 2012

This will change the numeric literals referenced in the dot-e files to enumerated constant names and declare these names as an enum.