Pastey 715.ex
- Posted by SDPringle Jan 02, 2012
-- 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.