Namespaces
- Posted by jbrown105 at HotPOP.com Apr 29, 2001
- 662 views
--7JfCtLOvnd9MIVvH Why doesn't euphoria support inline namespaces? it would make combining include file much easier! instead, if you want namespaces, you either have to write a program that pulls them out into seperate files, or you have to write a program that renames the variables & routines in a program, like I did. Anyone know why? TIA, jbrown P.S. I inclose a namespace program in this email, and it renames the data, not make a hundred diffrent include files. -- Linux User:190064 Linux Machine:84163 http://jbrown105.1avenue.com --7JfCtLOvnd9MIVvH Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="namespace.ex" --namespace.ex --based on my combine.ex --based on David Cuny's concat.ex --Altered to adjust name according to namespace --Supports routine_id-ing routines in namespace --Doesn't support multiple namespaces (one inside the other) yet. --JBrown --combine.ex --global scopes aren't redefined --this MIGHT cause an error, however, euphoria should normally have an --error in that case too. --procedure-scope vars aren't saved, this makes code more readable --N/A if shroud is on --you can either choose not to combine files in a list, or --you can ignore include files on 1 dir (default: eu's include dir) --shrouding symbols is optional. --bug fixed: local symbols were being treated as global. --bug fixed: strings with \x were changed to \x\x. --bug fixed: file c:\myfile.e and myfile.e were the diffrent files. --added platform to sequence builtin --bug: using routine_id("abort_") gives error --"Unable to resolve routine id for abort" --to fix made routine_id-ing of builtin routines legal. with trace -- concat.ex -- version 1.0 -- -- replacement for Euphoria's bind routine include get.e include file.e include wildcard.e include misc.e integer slash, IGNORE if platform() = 3 then slash = '/' else slash = '\\' end if IGNORE = 0 sequence ignore_table, ignore_dir ignore_dir = getenv("EUDIR")&slash&"include" if ignore_dir[1] = -1 then ignore_dir = "include" end if ignore_table={ --the default euphoric files "dll.e", "file.e", "get.e", "graphics.e", "image.e", "machine.e", "misc.e", "mouse.e", "msgbox.e", "safe.e", "sort.e", "wildcard.e", ""} sequence charClass -- character classes constant DIGIT = 1, OTHER = 2, LETTER = 3, BRACKET = 4, QUOTE = 5, DASH = 6, WHITE_SPACE = 7, NEW_LINE = 8 charClass = repeat( OTHER, 255 ) charClass['a'..'z'] = LETTER charClass['A'..'Z'] = LETTER charClass['_'] = LETTER charClass['0'..'9'] = DIGIT charClass['['] = BRACKET charClass[']'] = BRACKET charClass['('] = BRACKET charClass[')'] = BRACKET charClass['{'] = BRACKET charClass['}'] = BRACKET charClass['\''] = QUOTE charClass['"'] = QUOTE charClass[' '] = WHITE_SPACE charClass['\t'] = WHITE_SPACE charClass['\n'] = NEW_LINE charClass['-'] = DASH "constant", "do", "else", "elsif", "end", "exit", "for", "function", "global", "if", "include", "not", "or", "procedure", "profile", "profile_time", "return", "to", "type", "type_check", "then", "warning", "while", "with", "without", "xor", "namespace"} --not really builtin, but treated so "and_bits", "append", "arctan", "atom", "call", "c_func", "c_proc", "call_func", "call_proc", "clear_screen", "close", "command_line", "compare", "cos", "date", "equal", "find", "floor", "get_key", "get_pixel", "getc", "getenv", "gets", "integer", "length", "log", "machine_func", "machine_proc", "match", "mem_copy", "mem_set", "not_bits", "object", "open", "or_bits", "peek", "peek4s", "peek4u", "pixel", "poke", "poke4", "position", "power", "prepend", "print", "printf", "profile", "puts", "rand", "remainder", "repeat", "routine_id", "sequence", "sin", "sprintf", "sqrt", -- missing "system", "system_exec", "tan", "time", "trace", "platform", "xor_bits" } ids, -- count of ids issued outFile, -- file to write to addtype, nextGoff, inname globalState = 0 routineFlag = 0 procState = 0 ids = 0 addtype = 0 nextGoff = 0 inname = 0 sequence oldProc, newProc, oldLocal, newLocal, oldGlobal, newGlobal, included, types, all_ids, name, names oldProc = {} newProc = {} oldLocal = {} newLocal = {} oldGlobal = {} newGlobal = {} included = {} types = {"atom", "integer", "object", "sequence"} all_ids = {} name = {} names = {} constant EuPlace = getenv( "EUDIR" ), --Place = { "", EuPlace & "\\", EuPlace & "\\INCLUDE\\" } Place = { current_dir()&slash, EuPlace & slash, EuPlace & slash&"include"&slash, "" } -- returns where a file is -- looks in the usual places -- look in the usual places --trace(1) if find(fName[length(fName)], {10, 13}) then fName = fName[1..length(fName)-1] end if for i = 1 to length( Place ) do if sequence( dir( Place[i] & fName ) ) then if platform() = 3 then return Place[i] & fName else return upper( Place[i] & fName ) end if end if end for printf( 1, "Unable to locate file %s.\n", {fName} ) abort(0) end function function curnames() sequence s s = "" for i = 1 to length(name) do s &= name[i] &"_" end for return s end function integer at sequence new --if equal(word, "char") then --trace(1) --end if -- negates global? if globalState = 2 and find( word, { "constant", "for","function","procedure","type" } ) then -- clear global flag globalState = 0 elsif nextGoff then globalState = 0 nextGoff = 0 end if if addtype then types &= {word} addtype = 0 end if if globalState = 2 and find(word, types) then globalState = 0 end if -- ignore if builtin if find( word, builtin ) then if equal(word, "type") then addtype = 1 end if return word --commented out so local types can be redefined end if -- ignore if identifier if find( word, identifier ) then return word end if -- scoped to current procedure? -- scopes reversed so last redefinition will be used if procState = 2 then --at = find( word, reverse(oldProc) ) at = find( word, oldProc ) if at then return newProc[at] end if end if -- scoped to current module? -- scopes reversed so last redefinition will be used --at = find( word, reverse(oldLocal) ) at = find( word, oldLocal ) if at then return newLocal[at] end if -- scoped to globals? -- scopes reversed so last redefinition will be used --at = find( word, reverse(oldGlobal) ) at = find( word, oldGlobal ) if at then return newGlobal[at] end if -- not found; add to appropriate list --if SHROUD_ON then --new = sprintf( "id_%d", {ids} ) --else new = word if globalState = 0 then --never change a global name --if find(new, all_ids) then new = sprintf( "%s%s", {curnames(), word} ) names &= {word} word = new --end if end if --end if if procState != 2 then --only add globals and locals, procs don't go in all_ids &= {new} --but proc names do. ids += 1 end if if procState = 2 then -- defined in a proc oldProc = append( oldProc, word ) newProc = append( newProc, new ) elsif globalState then -- global declaration oldGlobal = append( oldGlobal, word ) newGlobal = append( newGlobal, new ) else -- local oldLocal = append( oldLocal, word ) newLocal = append( newLocal, new ) end if return new end function function checkn(sequence word) if find(word, names) then return 1 end if return 0 end function integer at, char, i sequence out, word integer namewaiting, needtoreplace namewaiting = 0 needtoreplace = 0 out = {} at = 1 while at <= length( s ) do -- get a character char = s[at] -- identifier if charClass[char] = LETTER then word = {} -- read until end while charClass[char] = LETTER or charClass[char] = DIGIT do -- add to word word = append( word, char ) -- next letter at += 1 char = s[at] end while -- routine flag routineFlag = equal( word, "routine_id" ) needtoreplace = checkn(word) if equal(word, "namespace") then if inname = 0 then --need to change to support multiple names name = append(name, "") namewaiting = 1 inname = 1 else inname = 0 names = "" name = name[1..length(name)-1] end if out = "--" & out --comment out elsif namewaiting then namewaiting = 0 name[length(name)] = word else -- substitute? word = replaceWord( word ) end if -- global flag if equal( word, "global" ) then -- new occurance globalState = 1 elsif globalState = 1 then -- mark as used globalState = 2 end if -- manage proc state if equal( word, "function" ) or equal( word, "procedure" ) or equal( word, "type" ) then if procState = 0 then -- beginning of definition procState = 1 elsif procState = 2 then -- end function/procedure procState = 0 oldProc = {} newProc = {} end if elsif procState = 1 then -- move state ahead procState = 2 globalState = 0 end if -- substitute, if needed out = out & word -- number: handles hex as well elsif charClass[char] = DIGIT or char = '#' then word = {} -- read until end while charClass[char] = DIGIT or charClass[char] = LETTER or char = '#' do -- add to word word = append( word, char ) -- next letter at += 1 char = s[at] end while -- accumulated number out = out & word -- comment elsif char = '-' and s[at+1] = '-' then -- comment out = out & s[at..length(s)] -- move past end at = length(s)+1 -- character literal elsif char = '\'' then at += 1 if s[at] = '\\' then -- special at += 1 word = "'\\" & s[at] & "'" else -- normal word = "'" & s[at] & "'" end if -- move past quote at += 2 -- accumulate out = out & word -- quote elsif char = '"' then word = {'"'} while 1 do -- move ahead at += 1 -- special? if s[at] = '\\' then at += 1 --word = word & s[at-1] & s[at] word = word & '\\' & s[at] -- prevent reading as quote s[at] = ' ' else word = word & s[at] end if -- end of quote? if s[at] = '"' then -- move ahead and exit at += 1 exit end if end while -- handle routine_id if routineFlag then needtoreplace = 1 end if if needtoreplace then if routineFlag then -- remove quotes word = word[2..length(word)-1] end if if find(word, names) then word = curnames() & names[find(word, names)] end if -- scoped to current procedure? i = 0 if procState = 2 then i = find( word, oldProc ) if i then word = newProc[i] end if end if -- not found in procedure? if i = 0 then -- scoped to current module? i = find( word, oldLocal ) if i then word = newLocal[i] end if end if -- not found procedure or module? if i = 0 then -- scoped to current module? i = find( word, oldGlobal ) if i then word = newGlobal[i] end if end if if find(word, builtin) or find(word, identifier) then i = 1 word = word --so routine_id("abort_") will work end if if i = 0 then printf( 1, "Unable to resolve routine id for %s\n", {word} ) abort(0) end if -- re-apply quotes word = '"' & word & '"' end if -- accumulated out = out & word -- delimiter else out = out & char at += 1 end if end while return out end function -- if the statement is an include statement, return the file name integer at -- include statement missing? if not match( "include ", data ) then return "" end if -- trim white space while charClass[ data[1] ] = WHITE_SPACE do data = data[2..length( data ) ] end while -- line feed? if find( '\n', data ) then data = data[1..length(data)-1] end if -- not first statement? if not equal( data[1..8], "include " ) then -- not an include statement return "" else -- remove statement data = data[9..length(data)] end if -- remove data after space at = find( ' ', data ) if at then data = data[1..at-1] end if return data end function -- if statement is a with/without instruction, comment it out -- include statement missing? if match( "with ", data ) or match( "without ", data ) then -- trim white space while charClass[ data[1] ] = WHITE_SPACE do data = data[2..length( data ) ] end while -- first statement? if length( data ) > 8 then if equal( data[1..5], "with " ) or equal( data[1..8], "without " ) then -- comment out data = "-- " & data end if end if end if return data end function function trimer(sequence s) sequence t integer u if s[length(s)] = '\n' then s = s[1..length(s)-1] end if if s[length(s)] = '\r' then s = s[1..length(s)-1] end if t = reverse(s) u = find(slash, t) if not u then return s end if t = t[1..u-1] s = reverse(t) return s end function function includable(sequence name) --IGNORE=1 is table, IGNORE=2 is dir sequence s if IGNORE = 0 then return 1 elsif IGNORE = 1 then if not find(name, ignore_table) then return 1 else return 0 end if elsif IGNORE = 2 then s = dir(ignore_dir) if atom(s) then return 1 end if s = s[3..length(s)] --skip '.' and '..' for i = 1 to length(s) do s[i] = s[i][D_NAME] end for if not find(name, s) then return 1 else return 0 end if end if return 0 --unknown IGNORE option, so always ignore end function integer inFile sequence newPrior, oldPrior, includeName object data -- find the file fName = findFile( fName ) -- already part of the file? if find( fName, included ) then return else included = append( included, fName ) end if -- store locals and clear oldPrior = oldLocal newPrior = newLocal oldLocal = {} newLocal = {} -- write header --puts( outFile, "\n" ) --puts( outFile, repeat( '-', 80 ) & "\n" ) --puts( outFile, repeat( '-', 80 ) & "\n" ) --printf( outFile, "-- INCLUDE FILE: %s\n", {fName} ) --printf( outFile, "--file %s\n", {fName} ) --puts( outFile, repeat( '-', 80 ) & "\n" ) --puts( outFile, repeat( '-', 80 ) & "\n" ) --puts( outFile, "\n" ) inFile = open( fName, "r" ) while 1 do -- read a line data = gets( inFile ) -- end of file? if integer( data ) then exit end if -- include file? includeName = getIncludeName( data ) --if match("file.e", includeName) then trace(1) end if --if length( includeName ) and includable(trimer(includeName)) then -- include the file --parseFile( includeName ) if length(includeName) then --no parse puts( outFile, data ) elsif sequence(data) and length(data) >= 2 and equal(data[1..2], "#!") then --remove all #! puts( outFile, "--"&data ) else -- translate data = parseLine( data ) -- remove with/without data = removeWith( data ) -- output puts( outFile, data ) end if end while close( inFile ) --end of file header --puts( outFile, "\n" ) --printf( outFile, "--end of file %s\n", {fName} ) --puts( outFile, "\n" ) -- restore locals oldLocal = oldPrior newLocal = newPrior end procedure procedure command_length(integer i, sequence s) if length(s) > i then printf(2, "\nError - too many parameters! - %s \n", {s[i+1]}) abort(2) end if end procedure procedure get_options(sequence c) if equal(c[1], "--table") then command_length(5, command_line()) IGNORE = 1 elsif equal(c[1], "--dir") then command_length(6, command_line()) IGNORE = 2 if length(c) = 2 then ignore_dir = c[2] end if else --simulate too many parameters command_length(4, command_line()) end if end procedure sequence cmd, inFileName, outFileName -- read the command line cmd = command_line() -- get input file if length( cmd ) > 2 then inFileName = cmd[3] else inFileName = prompt_string( "File to concatonate? " ) if length( inFileName ) = 0 then abort(0) end if end if -- get output file if length( cmd ) > 3 then outFileName = cmd[4] else outFileName = prompt_string( "File to create? " ) if length( outFileName ) = 0 then abort(0) end if end if --trace(1) if length(cmd) > 4 then get_options(cmd[5..length(cmd)]) end if -- make sure they are different if equal( inFileName, outFileName ) then puts( 1, "File names must be different!\n" ) abort(0) end if -- open the file outFile = open( outFileName, "w" ) puts(outFile, "--This file was created by namespace.ex\n") puts(outFile, "--by JBrown at jbrown105 at hotpop.com\n") puts(outFile, "--based on concat.ex, by David Cuny\n") -- process the input file parseFile( inFileName ) -- close the output file close( outFile ) end procedure run() --7JfCtLOvnd9MIVvH--