slicc: have a central mechanism for creating a code_formatter.
authorNathan Binkert <nate@binkert.org>
Thu, 11 Mar 2010 00:22:26 +0000 (16:22 -0800)
committerNathan Binkert <nate@binkert.org>
Thu, 11 Mar 2010 00:22:26 +0000 (16:22 -0800)
This makes it easier to add global variables like protocol

20 files changed:
src/mem/protocol/SConscript
src/mem/slicc/ast/AST.py
src/mem/slicc/ast/ActionDeclAST.py
src/mem/slicc/ast/AssignStatementAST.py
src/mem/slicc/ast/CheckStopSlotsStatementAST.py
src/mem/slicc/ast/ExprAST.py
src/mem/slicc/ast/ExprStatementAST.py
src/mem/slicc/ast/FuncDeclAST.py
src/mem/slicc/ast/IfStatementAST.py
src/mem/slicc/ast/InPortDeclAST.py
src/mem/slicc/ast/InfixOperatorExprAST.py
src/mem/slicc/ast/MemberExprAST.py
src/mem/slicc/ast/MethodCallExprAST.py
src/mem/slicc/ast/OutPortDeclAST.py
src/mem/slicc/parser.py
src/mem/slicc/symbols/Func.py
src/mem/slicc/symbols/StateMachine.py
src/mem/slicc/symbols/SymbolTable.py
src/mem/slicc/symbols/Type.py
src/python/m5/util/code_formatter.py

index 2c29ea37458efbd4a635cdd7ff03a4f73bf05ad7..5f64938c6558fd86389878a2056fe1bd1281b99d 100644 (file)
@@ -63,8 +63,9 @@ def slicc_scanner(node, env, path):
 env.Append(SCANNERS=Scanner(function=slicc_scanner,skeys=['.slicc']))
 
 def slicc_emitter(target, source, env):
+    protocol = source[0].get_contents()
     files = [s.srcnode().abspath for s in source[1:]]
-    slicc = SLICC(debug=True)
+    slicc = SLICC(protocol, debug=True)
     print "SLICC parsing..."
     for name in slicc.load(files, verbose=True):
         print "    %s" % name
@@ -104,7 +105,7 @@ def slicc_action(target, source, env):
     if not isdir(hdir):
         os.mkdir(hdir)
 
-    slicc = SLICC(debug=True)
+    slicc = SLICC(protocol, debug=True)
     files = [str(s) for s in source[1:]]
     slicc.load(files, verbose=False)
 
index 5b1b124cdc98d20b1b7ac063969937fc34345d89..5818448ca5fd9bad75bed9b514faf1df25bc70a4 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.util import PairContainer, Location
 
 class AST(PairContainer):
@@ -54,7 +52,7 @@ class AST(PairContainer):
     def embedError(self, message, *args):
         if args:
             message = message % args
-        code = code_formatter()
+        code = self.slicc.codeFormatter()
         code('''
 cerr << "Runtime Error at ${{self.location}}, Ruby Time: " << g_eventQueue_ptr->getTime() << ": "<< $message << ", PID: " << getpid() << endl;
 char c; cerr << "press return to continue." << endl; cin.get(c); abort();
index 18bf443b925fa9d38b8b94b144aad1221f93f53f..e85aa25b80706c1b07805fcea5fa2235687e7247 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.DeclAST import DeclAST
 from slicc.symbols import Action, Type, Var
 
@@ -55,7 +53,7 @@ class ActionDeclAST(DeclAST):
             self.symtab.newSymbol(var)
 
             # Do not allows returns in actions
-            code = code_formatter()
+            code = self.slicc.codeFormatter()
             self.statement_list.generate(code, None)
             self.pairs["c_code"] = str(code)
 
index f8e77b03b4126e0796d1cfbf25b352fcaedfadcd..3c3426f5b0c58a356bc37ec5992641626bc74625 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.StatementAST import StatementAST
 
 class AssignStatementAST(StatementAST):
@@ -39,8 +37,8 @@ class AssignStatementAST(StatementAST):
         return "[AssignStatementAST: %r := %r]" % (self.lvalue, self.rvalue)
 
     def generate(self, code, return_type):
-        lcode = code_formatter()
-        rcode = code_formatter()
+        lcode = self.slicc.codeFormatter()
+        rcode = self.slicc.codeFormatter()
 
         ltype = self.lvalue.generate(lcode)
         rtype = self.rvalue.generate(rcode)
index 307fbd6a15b0762d1864614a51b0c8beb95cb89c..9320aebac467aaab7d44ef94529cfa9f857ad483 100644 (file)
@@ -45,7 +45,7 @@ class CheckStopSlotsStatementAST(StatementAST):
         var = self.variable.var
         assert var not in self.resources
 
-        check_code = code_formatter()
+        check_code = self.slicc.codeFormatter()
         if self.condStr == "((*in_msg_ptr)).m_isOnChipSearch":
             check_code('''
 const Response9Msg* in_msg_ptr =
index 70a0aa0b5927e181692cf11f833ea0d1bafa0c61..393101112d3745950e764ec36e6a1d5584f6ee22 100644 (file)
@@ -24,8 +24,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.AST import AST
 
 class ExprAST(AST):
@@ -37,7 +35,7 @@ class ExprAST(AST):
         pass
 
     def inline(self, get_type=False):
-        code = code_formatter(fix_newlines=False)
+        code = self.slicc.codeFormatter(fix_newlines=False)
         return_type = self.generate(code)
         if get_type:
             return return_type, code
index b16d1d0729f0ffc2571d86495f69d83298bb2357..898fccf3deff8a4d5b33219d8c05dbb5acf1f842 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.StatementAST import StatementAST
 from slicc.symbols import Type
 
index 980804c2af9797301243d76e67585da59f633262..a87d61119efc24de4750ec6d3bb0551fd0fd500a 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util.code_formatter import code_formatter
-
 from slicc.ast.DeclAST import DeclAST
 from slicc.symbols import Func, Type
 
@@ -70,7 +68,7 @@ class FuncDeclAST(DeclAST):
             types.append(type)
             params.append(ident)
 
-        body = code_formatter()
+        body = self.slicc.codeFormatter()
         if self.statements is None:
             self["external"] = "yes"
         else:
index 788876fd1184ef803298ebc52b11a7a113ba8bea..359173203c8b749c4be84596a22317394096094e 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.StatementAST import StatementAST
 from slicc.symbols import Type
 
@@ -45,7 +43,7 @@ class IfStatementAST(StatementAST):
         return "[IfStatement: %r%r%r]" % (self.cond, self.then, self.else_)
 
     def generate(self, code, return_type):
-        cond_code = code_formatter()
+        cond_code = self.slicc.codeFormatter()
         cond_type = self.cond.generate(cond_code)
 
         if cond_type != self.symtab.find("bool", Type):
index 3dde24557e15b55fcbb6f4bcafca78a0e8d3df41..ad48ea4b807dec3cd5aa45ceb27e920fccd39d50 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.DeclAST import DeclAST
 from slicc.ast.TypeAST import TypeAST
 from slicc.symbols import Func, Type, Var
@@ -48,7 +46,7 @@ class InPortDeclAST(DeclAST):
         symtab = self.symtab
         void_type = symtab.find("void", Type)
 
-        code = code_formatter()
+        code = self.slicc.codeFormatter()
         queue_type = self.var_expr.generate(code)
         if not queue_type.isInPort:
             self.error("The inport queue's type must have the 'inport' " + \
@@ -115,7 +113,7 @@ class InPortDeclAST(DeclAST):
         symtab.newSymbol(func)
 
         if self.statements is not None:
-            rcode = code_formatter()
+            rcode = self.slicc.codeFormatter()
             rcode.indent()
             rcode.indent()
             self.statements.generate(rcode, None)
index c4fb4a4db8e98df9956debf8177fb3d0201c451b..c5f384c4b009190b6b30bb652d8c876c5d1efe72 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.ExprAST import ExprAST
 from slicc.symbols import Type
 
@@ -42,8 +40,8 @@ class InfixOperatorExprAST(ExprAST):
         return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right)
 
     def generate(self, code):
-        lcode = code_formatter()
-        rcode = code_formatter()
+        lcode = self.slicc.codeFormatter()
+        rcode = self.slicc.codeFormatter()
 
         ltype = self.left.generate(lcode)
         rtype = self.right.generate(rcode)
index c62e287416080886f9c8d99b83ee5813a31e6a5c..8f6b4a55c69370bda4404e10f09e607e6d189b27 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.ExprAST import ExprAST
 
 class MemberExprAST(ExprAST):
index 150f391bc9798c5f30bcd8ec5fdd53116c93bd45..84009c076ec921445a32f69b8a5027b8132ce43a 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.ExprAST import ExprAST
 
 class MethodCallExprAST(ExprAST):
@@ -36,7 +34,7 @@ class MethodCallExprAST(ExprAST):
         self.expr_ast_vec = expr_ast_vec
 
     def generate(self, code):
-        tmp = code_formatter()
+        tmp = self.slicc.codeFormatter()
         paramTypes = []
         for expr_ast in self.expr_ast_vec:
             return_type = expr_ast.generate(tmp)
@@ -91,7 +89,7 @@ class MemberMethodCallExprAST(MethodCallExprAST):
                                               self.obj_expr_ast,
                                               self.expr_ast_vec)
     def generate_prefix(self, paramTypes):
-        code = code_formatter()
+        code = self.slicc.codeFormatter()
 
         # member method call
         obj_type = self.obj_expr_ast.generate(code)
index a387f6d910c5dad433ce490e25ae09c94ccecb42..39795ef7ee8fc2859d506e20e78cfb5519c63b5d 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.ast.DeclAST import DeclAST
 from slicc.ast.TypeAST import TypeAST
 from slicc.symbols import Var
@@ -45,7 +43,7 @@ class OutPortDeclAST(DeclAST):
         return "[OutPortDecl: %r]" % self.ident
 
     def generate(self):
-        code = code_formatter(newlines=False)
+        code = self.slicc.codeFormatter(newlines=False)
 
         queue_type = self.var_expr.generate(code)
         if not queue_type.isOutPort:
index 99b8fa5f40dce219af1b394b278d64734ae0702d..ae8a9342f2db9871509a0a3f1a439377b538ebb9 100644 (file)
@@ -30,6 +30,7 @@ import os.path
 import re
 import sys
 
+from m5.util import code_formatter
 from m5.util.grammar import Grammar, TokenError, ParseError
 
 import slicc.ast as ast
@@ -50,11 +51,17 @@ def read_slicc(sources):
             yield sm_file
 
 class SLICC(Grammar):
-    def __init__(self, **kwargs):
+    def __init__(self, protocol, **kwargs):
         super(SLICC, self).__init__(**kwargs)
         self.decl_list_vec = []
         self.current_file = None
-        self.symtab = SymbolTable()
+        self.protocol = protocol
+        self.symtab = SymbolTable(self)
+
+    def codeFormatter(self, *args, **kwargs):
+        code = code_formatter(*args, **kwargs)
+        code['protocol'] = self.protocol
+        return code
 
     def parse(self, filename):
         self.current_file = filename
index 5c812a96f4f3c2ccdbc7e4c653bdbc99c1e9b238..a05f0a03ba9bd76355c4bb37f1582bf793b799f6 100644 (file)
@@ -25,8 +25,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter
-
 from slicc.symbols.Symbol import Symbol
 from slicc.symbols.Type import Type
 
@@ -71,7 +69,7 @@ class Func(Symbol):
         if "external" in self:
             return
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
 
         # Header
         code('''
index b5c12fe25b5f65f50b51a2bab1887b4e6d98a56f..5da42a6d5145b4876fad016144c44a5cb4eff666 100644 (file)
@@ -25,7 +25,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter, orderdict
+from m5.util import orderdict
 
 from slicc.symbols.Symbol import Symbol
 from slicc.symbols.Var import Var
@@ -150,7 +150,7 @@ class StateMachine(Symbol):
             func.writeCodeFiles(path)
 
     def printControllerPython(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
         py_ident = "%s_Controller" % ident
         c_ident = "%s_Controller" % self.ident
@@ -180,7 +180,7 @@ class $py_ident(RubyController):
 
     def printControllerHH(self, path):
         '''Output the method declarations for the class declaration'''
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
         c_ident = "%s_Controller" % self.ident
 
@@ -301,7 +301,7 @@ static int m_num_controllers;
     def printControllerCC(self, path):
         '''Output the actions for performing the actions'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
         c_ident = "%s_Controller" % self.ident
 
@@ -641,7 +641,7 @@ void $c_ident::${{action.ident}}(const Address& addr)
     def printCWakeup(self, path):
         '''Output the wakeup loop for the events'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
@@ -696,7 +696,7 @@ void ${ident}_Controller::wakeup()
     def printCSwitch(self, path):
         '''Output switch statement for transition table'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
@@ -778,7 +778,7 @@ TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, $
             case_string = "%s_State_%s, %s_Event_%s" % \
                 (self.ident, trans.state.ident, self.ident, trans.event.ident)
 
-            case = code_formatter()
+            case = self.symtab.codeFormatter()
             # Only set next_state if it changes
             if trans.state != trans.nextState:
                 ns_ident = trans.nextState.ident
@@ -853,7 +853,7 @@ if (!%s.areNSlotsAvailable(%s)) {
         code.write(path, "%s_Transitions.cc" % self.ident)
 
     def printProfilerHH(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
@@ -888,7 +888,7 @@ class ${ident}_Profiler {
         code.write(path, "%s_Profiler.hh" % self.ident)
 
     def printProfilerCC(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
@@ -967,7 +967,7 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
     # **************************
     def frameRef(self, click_href, click_target, over_href, over_target_num,
                  text):
-        code = code_formatter(fix_newlines=False)
+        code = self.symtab.codeFormatter(fix_newlines=False)
         code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""")
         return str(code)
 
@@ -998,7 +998,7 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
             code.write(path, name)
 
     def printHTMLTransitions(self, path, active_state):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
 
         code('''
 <HTML><BODY link="blue" vlink="blue">
index deb971eb9b2d68838f43aa807f4f849ab47437ef..dd45ac06c0cf98215f9039edbc6aa38a137d427e 100644 (file)
@@ -33,7 +33,9 @@ from slicc.symbols.Type import Type
 from slicc.util import Location
 
 class SymbolTable(object):
-    def __init__(self):
+    def __init__(self, slicc):
+        self.slicc = slicc
+
         self.sym_vec = []
         self.sym_map_vec = [ {} ]
         self.machine_components = {}
@@ -52,6 +54,9 @@ class SymbolTable(object):
     def __repr__(self):
         return "[SymbolTable]" # FIXME
 
+    def codeFormatter(self, *args, **kwargs):
+        return self.slicc.codeFormatter(*args, **kwargs)
+
     def newSymbol(self, sym):
         self.registerSym(str(sym), sym)
         self.sym_vec.append(sym)
@@ -118,7 +123,7 @@ class SymbolTable(object):
                 yield symbol
 
     def writeCodeFiles(self, path):
-        code = code_formatter()
+        code = self.codeFormatter()
         code('''
 /** Auto generated C++ code started by $__file__:$__line__ */
 
@@ -140,7 +145,7 @@ class SymbolTable(object):
         else:
             name = "empty.html"
 
-        code = code_formatter()
+        code = self.codeFormatter()
         code('''
 <html>
 <head>
@@ -154,7 +159,7 @@ class SymbolTable(object):
 ''')
         code.write(path, "index.html")
 
-        code = code_formatter()
+        code = self.codeFormatter()
         code("<HTML></HTML>")
         code.write(path, "empty.html")
 
index 41032e233bfe2856b8060e4cfc54267d9c5f2ffd..3f39ec20811d984eccc1ba2a3baee895cebe7ecf 100644 (file)
@@ -25,7 +25,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter, orderdict
+from m5.util import orderdict
 
 from slicc.util import PairContainer
 from slicc.symbols.Symbol import Symbol
@@ -191,7 +191,7 @@ class Type(Symbol):
             self.printTypeCC(path)
 
     def printTypeHH(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         code('''
 /** \\file ${{self.c_ident}}.hh
  *
@@ -375,7 +375,7 @@ ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
         code.write(path, "%s.hh" % self.c_ident)
 
     def printTypeCC(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
 
         code('''
 /** \\file ${{self.c_ident}}.cc
@@ -412,7 +412,7 @@ void ${{self.c_ident}}::print(ostream& out) const
         code.write(path, "%s.cc" % self.c_ident)
 
     def printEnumHH(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         code('''
 /** \\file ${{self.c_ident}}.hh
  *
@@ -470,7 +470,7 @@ ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
         code.write(path, "%s.hh" % self.c_ident)
 
     def printEnumCC(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         code('''
 /** \\file ${{self.c_ident}}.hh
  *
index 396fe0e52fa647e17f736cb3fd26dcfed1f3feec..47106e0d94cd7add6572a159db85b651a4b6ff01 100644 (file)
@@ -55,15 +55,14 @@ class lookup(object):
         if item == '__line__':
             return self.frame.f_lineno
 
+        if self.formatter.locals and item in self.frame.f_locals:
+            return self.frame.f_locals[item]
+
         if item in self.dict:
             return self.dict[item]
 
-        if self.formatter.locals or self.formatter.globals:
-            if self.formatter.locals and item in self.frame.f_locals:
-                return self.frame.f_locals[item]
-
-            if self.formatter.globals and item in self.frame.f_globals:
-                return self.frame.f_globals[item]
+        if self.formatter.globals and item in self.frame.f_globals:
+            return self.frame.f_globals[item]
 
         if item in __builtin__.__dict__:
             return __builtin__.__dict__[item]
@@ -124,7 +123,7 @@ class code_formatter(object):
         self._dict = {}
         self._indent_level = 0
         self._indent_spaces = 4
-        self.globals = kwargs.pop('globals',type(self).globals)
+        self.globals = kwargs.pop('globals', type(self).globals)
         self.locals = kwargs.pop('locals', type(self).locals)
         self._fix_newlines = \
                 kwargs.pop('fix_newlines', type(self).fix_newlines)