diff options
author | rahulp13 | 2023-06-13 18:10:16 +0530 |
---|---|---|
committer | rahulp13 | 2023-06-13 18:10:16 +0530 |
commit | 172debd60ec1bae09c6b9c9180a388628e819909 (patch) | |
tree | d37e6da4a8ed3dbaf761751df3d3224662a611bf /src | |
parent | 2ed5f8dce60da2dfde8cf36a8f8b29d3c2fb1107 (diff) | |
download | eSim-172debd60ec1bae09c6b9c9180a388628e819909.tar.gz eSim-172debd60ec1bae09c6b9c9180a388628e819909.tar.bz2 eSim-172debd60ec1bae09c6b9c9180a388628e819909.zip |
maker module flake8 compliant & added docstrings
Diffstat (limited to 'src')
-rw-r--r-- | src/configuration/Appconfig.py | 2 | ||||
-rwxr-xr-x | src/frontEnd/ProjectExplorer.py | 2 | ||||
-rwxr-xr-x | src/kicadtoNgspice/DeviceModel.py | 6 | ||||
-rw-r--r-- | src/kicadtoNgspice/KicadtoNgspice.py | 6 | ||||
-rw-r--r-- | src/kicadtoNgspice/Model.py | 7 | ||||
-rwxr-xr-x | src/maker/Maker.py | 2 | ||||
-rwxr-xr-x | src/maker/ModelGeneration.py | 204 | ||||
-rwxr-xr-x | src/maker/NgVeri.py | 46 | ||||
-rwxr-xr-x | src/ngspicetoModelica/NgspicetoModelica.py | 2 |
9 files changed, 160 insertions, 117 deletions
diff --git a/src/configuration/Appconfig.py b/src/configuration/Appconfig.py index c3f14e6f..00977ca0 100644 --- a/src/configuration/Appconfig.py +++ b/src/configuration/Appconfig.py @@ -10,7 +10,7 @@ # BUGS: --- # NOTES: --- # AUTHOR: Fahim Khan, fahim.elex@gmail.com -# MODIFIED: Rahul Paknikar, rahulp@cse.iitb.ac.in +# MODIFIED: Rahul Paknikar, rahulp@iitb.ac.in # ORGANIZATION: eSim Team at FOSSEE, IIT Bombay # CREATED: Tuesday 24 February 2015 # REVISION: Tuesday 13 September 2022 diff --git a/src/frontEnd/ProjectExplorer.py b/src/frontEnd/ProjectExplorer.py index 77c9352e..99772378 100755 --- a/src/frontEnd/ProjectExplorer.py +++ b/src/frontEnd/ProjectExplorer.py @@ -78,7 +78,7 @@ class ProjectExplorer(QtWidgets.QWidget): def refreshInstant(self): for i in range(self.treewidget.topLevelItemCount()): - if(self.treewidget.topLevelItem(i).isExpanded()): + if self.treewidget.topLevelItem(i).isExpanded(): index = self.treewidget.indexFromItem( self.treewidget.topLevelItem(i)) self.refreshProject(indexItem=index) diff --git a/src/kicadtoNgspice/DeviceModel.py b/src/kicadtoNgspice/DeviceModel.py index f16b30ab..7fb9776e 100755 --- a/src/kicadtoNgspice/DeviceModel.py +++ b/src/kicadtoNgspice/DeviceModel.py @@ -693,7 +693,7 @@ class DeviceModel(QtWidgets.QWidget): # Sumanto Kar, sumantokar@iitb.ac.in # Nagesh Karmali, nags@cse.iitb.ac.in # Firuza Karmali, firuza@cse.iitb.ac.in - # Rahul Paknikar, rahulp@cse.iitb.ac.in + # Rahul Paknikar, rahulp@iitb.ac.in # GUIDED BY: # Kunal Ghosh, VLSI System Design Corp.Pvt.Ltd # Anagha Ghosh, VLSI System Design Corp.Pvt.Ltd @@ -756,9 +756,9 @@ class DeviceModel(QtWidgets.QWidget): outputlist.append(k) if '_OR_' in str(j): realoutputlist.append(k) - if '_W_' in str(j) and not(k in wirelist): + if '_W_' in str(j) and not (k in wirelist): wirelist.append(k) - if '_WR_' in str(j) and not(k in realwirelist): + if '_WR_' in str(j) and not (k in realwirelist): realwirelist.append(k) netnames[-1] = netnames[-1].replace("IPAD", '') diff --git a/src/kicadtoNgspice/KicadtoNgspice.py b/src/kicadtoNgspice/KicadtoNgspice.py index 6a919de9..231efd52 100644 --- a/src/kicadtoNgspice/KicadtoNgspice.py +++ b/src/kicadtoNgspice/KicadtoNgspice.py @@ -10,7 +10,7 @@ # BUGS: --- # NOTES: --- # AUTHOR: Fahim Khan, fahim.elex@gmail.com -# MODIFIED: Rahul Paknikar, rahulp@cse.iitb.ac.in +# MODIFIED: Rahul Paknikar, rahulp@iitb.ac.in # ORGANIZATION: eSim Team at FOSSEE, IIT Bombay # CREATED: Wednesday 04 March 2015 # REVISION: Sunday 18 September 2022 @@ -560,7 +560,7 @@ class MainWindow(QtWidgets.QWidget): attr_ui = ET.SubElement(attr_model, line[3], name="type") attr_ui.text = line[2] for key, value in line[7].items(): - if( + if ( hasattr(value, '__iter__') and i <= end and not isinstance(value, str) ): @@ -849,7 +849,7 @@ class MainWindow(QtWidgets.QWidget): for i in range(2, len(words) - 1): subcktInfo += words[i] + " " continue - if( + if ( words[0] == ".end" or words[0] == ".ac" or words[0] == ".dc" or diff --git a/src/kicadtoNgspice/Model.py b/src/kicadtoNgspice/Model.py index 1389e556..75c0eaf5 100644 --- a/src/kicadtoNgspice/Model.py +++ b/src/kicadtoNgspice/Model.py @@ -1,11 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from PyQt5 import QtWidgets, QtCore, QtGui -from PyQt5.QtCore import QObject, pyqtSlot +from PyQt5 import QtWidgets, QtCore from . import TrackWidget from xml.etree import ElementTree as ET import os -import sys class Model(QtWidgets.QWidget): @@ -16,7 +14,6 @@ class Model(QtWidgets.QWidget): """ # by Sumanto and Jay - def addHex(self): """ This function is use to keep track of all Device Model widget @@ -34,10 +31,8 @@ class Model(QtWidgets.QWidget): )[0] ) self.text = open(self.hexfile).read() - chosen_file_path = os.path.abspath(self.hexfile) # By Sumanto and Jay - def uploadHex(self): """ This function is use to keep track of all Device Model widget diff --git a/src/maker/Maker.py b/src/maker/Maker.py index e5d11988..b9895f21 100755 --- a/src/maker/Maker.py +++ b/src/maker/Maker.py @@ -472,7 +472,7 @@ class Handler(watchdog.events.PatternMatchingEventHandler): # self.obj_Appconfig.print_info("NgVeri File:\ # "+self.verilogfile+" modified. Please click on Refresh") global toggle_flag - if not(self.refreshoption in toggle_flag): + if self.refreshoption not in toggle_flag: toggle_flag.append(self.refreshoption) # i.rm_watch() self.observer.stop() diff --git a/src/maker/ModelGeneration.py b/src/maker/ModelGeneration.py index 49d5da0b..42ebd285 100755 --- a/src/maker/ModelGeneration.py +++ b/src/maker/ModelGeneration.py @@ -27,20 +27,20 @@ # ========================================================================= -# importing the files and libraries import re import os from PyQt5 import QtCore, QtWidgets from configparser import ConfigParser from configuration import Appconfig + from . import createkicad import hdlparse.verilog_parser as vlog -# Class is used to generate the Ngspice Model class ModelGeneration(QtWidgets.QWidget): - - # initialising the variables + ''' + Class is used to generate the Ngspice Model + ''' def __init__(self, file, termedit): QtWidgets.QWidget.__init__(self) super().__init__() @@ -72,11 +72,12 @@ class ModelGeneration(QtWidgets.QWidget): self.licensefile = self.parser.get('SRC', 'LICENSE') self.digital_home = self.parser.get( 'NGHDL', 'DIGITAL_MODEL') + "/Ngveri" - # # #### Creating connection_info.txt file from verilog file #### # - # Reading the file and performing operations and - # copying it in the Ngspice folder def verilogfile(self): + ''' + Reading the file and performing operations and + copying it in the Ngspice folder + ''' Text = "<span style=\" font-size:25pt;\ font-weight:1000; color:#008000;\" >" Text += ".................Running NgVeri..................." @@ -107,8 +108,10 @@ class ModelGeneration(QtWidgets.QWidget): f.write("\n") f.close() - # This function calls the sandpiper to convert .tlv file to .sv file def sandpiper(self): + ''' + This function calls the sandpiper to convert .tlv file to .sv file + ''' init_path = '../../' if os.name == 'nt': init_path = '' @@ -153,12 +156,12 @@ class ModelGeneration(QtWidgets.QWidget): os.chdir(self.cur_dir) self.fname = self.fname.split('.')[0] + ".sv" - # This function parses the module name and \ - # input/output ports of verilog code using HDL parse - # and writes to the connection_info.txt - def verilogParse(self): - + ''' + This function parses the module name and + input/output ports of verilog code using HDL parse + and writes to the "connection_info.txt". + ''' with open(self.modelpath + self.fname, 'rt') as fh: code = fh.read() @@ -218,9 +221,11 @@ class ModelGeneration(QtWidgets.QWidget): return "Error" return "No Error" - # This function is used to get the Port Information from - # connection_info.txt def getPortInfo(self): + ''' + This function is used to get the port information + from "connection_info.txt" + ''' readfile = open(self.modelpath + 'connection_info.txt', 'r') data = readfile.readlines() self.input_list = [] @@ -254,10 +259,11 @@ class ModelGeneration(QtWidgets.QWidget): for output in self.output_list: self.output_port.append(output[0] + ":" + output[2]) - # This function is used to create the cfunc.mod file in Ngspice folder - # automatically - def cfuncmod(self): + ''' + This function is used to create the "cfunc.mod" file + in Ngspice folder automatically. + ''' # ############# Creating content for cfunc.mod file ############## # @@ -397,12 +403,17 @@ and set the load for input ports */ }\n\n\ if(ANALYSIS == DC)\n\ {\n\ - OUTPUT_STATE(" + item.split(':')[0] + "[Ii]) = _op_" + item.split(':')[0] + "[Ii];\n\ + OUTPUT_STATE(" + item.split(':')[0] + + "[Ii]) = _op_" + item.split(':')[0] + "[Ii];\n\ }\n\ - else if(_op_" + item.split(':')[0] + "[Ii] != _op_" + item.split(':')[0] + "_old[Ii])\n\ + else if(_op_" + item.split(':')[0] + + "[Ii] != _op_" + item.split(':')[0] + "_old[Ii])\n\ {\n\ - OUTPUT_STATE(" + item.split(':')[0] + "[Ii]) = _op_" + item.split(':')[0] + "[Ii];\n\ - OUTPUT_DELAY(" + item.split(':')[0] + "[Ii]) = ((_op_" + item.split(':')[0] + "[Ii] == ZERO) ? PARAM(fall_delay) : PARAM(rise_delay));\n\ + OUTPUT_STATE(" + item.split(':')[0] + "[Ii]) = _op_" + + item.split(':')[0] + "[Ii];\n\ + OUTPUT_DELAY(" + item.split(':')[0] + "[Ii]) = ((_op_" + + item.split(':')[0] + + "[Ii] == ZERO) ? PARAM(fall_delay) : PARAM(rise_delay));\n\ }\n\ else\n\ {\n\ @@ -497,9 +508,11 @@ and set the load for input ports */ cfunc.write("\n}") cfunc.close() - # This function creates the ifspec file automatically in Ngspice folder - def ifspecwrite(self): + ''' + This function creates the ifspec file + automatically in Ngspice folder. + ''' print("Starting with ifspec.ifs file") ifspec = open(self.modelpath + 'ifspec.ifs', 'w') @@ -607,10 +620,11 @@ and set the load for input ports */ ifspec.write("\n") ifspec.close() - # This function creates the header file of sim_main file automatically in - # Ngspice folder - def sim_main_header(self): + ''' + This function creates the header file of + "sim_main" file automatically in Ngspice folder. + ''' print("Starting With sim_main_" + self.fname.split('.')[0] + ".h file") simh = open( self.modelpath + @@ -632,9 +646,11 @@ and set the load for input ports */ simh.write(item) simh.close() - # This function creates the sim_main file needed by verilator - # automatically in Ngspice folder def sim_main(self): + ''' + This function creates the "sim_main" file needed by verilator + automatically in Ngspice folder. + ''' print( "Starting With sim_main_" + self.fname.split('.')[0] + @@ -650,7 +666,8 @@ and set the load for input ports */ self.fname.split('.')[0] + ".cpp file") - comment = '''/* This is cfunc.mod file auto generated by gen_con_info.py + comment = \ + '''/* This is cfunc.mod file auto generated by gen_con_info.py Developed by Sumanto Kar at IIT Bombay */\n ''' @@ -680,7 +697,8 @@ and set the load for input ports */ extern "C" int foo_''' + self.fname.split('.')[0] + '''(int,int); ''') convert_func = ''' - void int2arr''' + self.fname.split('.')[0] + '''(int num, int array[], int n) + void int2arr''' + self.fname.split('.')[0] + \ + '''(int num, int array[], int n) { for (int i = 0; i < n && num>=0; i++) { @@ -700,17 +718,20 @@ and set the load for input ports */ int foo_''' + self.fname.split('.')[0] + '''(int init,int count) { static VerilatedContext* contextp = new VerilatedContext; - static V''' + self.fname.split('.')[0] + "* " + self.fname.split('.')[0] + '''[1024]; + static V''' + self.fname.split('.')[0] + "* " + \ + self.fname.split('.')[0] + '''[1024]; count--; if (init==0) { - ''' + self.fname.split('.')[0] + '''[count]=new V''' + self.fname.split('.')[0] + '''{contextp}; + ''' + self.fname.split('.')[0] + '''[count]=new V''' + \ + self.fname.split('.')[0] + '''{contextp}; contextp->traceEverOn(true); } else { contextp->timeInc(1); - printf("=============''' + self.fname.split('.')[0] + ''' : New Iteration==========="); + printf("=============''' + self.fname.split('.')[0] + \ + ''' : New Iteration==========="); printf("\\nInstance : %d\\n",count); printf("\\nInside foo before eval.....\\n"); ''' @@ -788,8 +809,10 @@ and set the load for input ports */ csim.write(item) csim.close() - # This function creates modpathlst in Ngspice folder def modpathlst(self): + ''' + This function creates modpathlst in Ngspice folder. + ''' print("Editing modpath.lst file") mod = open(self.digital_home + '/modpath.lst', 'r') text = mod.read() @@ -799,8 +822,11 @@ and set the load for input ports */ mod.write(self.fname.split('.')[0] + "\n") mod.close() - # This function is used to run the Verilator using the verilator commands def run_verilator(self): + ''' + This function is used to run the Verilator + using the verilator commands. + ''' init_path = '../../' if os.name == 'nt': init_path = '' @@ -841,8 +867,10 @@ and set the load for input ports */ print("Verilator Executed") os.chdir(self.cur_dir) - # Running make verilator using this function def make_verilator(self): + ''' + Running make verilator using this function + ''' self.cur_dir = os.getcwd() print("Make Verilator.............") os.chdir(self.modelpath) @@ -876,9 +904,11 @@ and set the load for input ports */ print("Make Verilator Executed") os.chdir(self.cur_dir) - # This function copies the verilator files/object files from - # src/xspice/icm/Ngveri/ to release/src/xspice/icm/Ngveri/ def copy_verilator(self): + ''' + This function copies the verilator files/object files from + "src/xspice/icm/Ngveri/ to release/src/xspice/icm/Ngveri/" + ''' self.cur_dir = os.getcwd() print("Copying the required files to Release Folder.............") os.chdir(self.modelpath) @@ -934,8 +964,10 @@ and set the load for input ports */ except BaseException: print("There is error in Copying Files ") - # Running the make command for Ngspice def runMake(self): + ''' + Running the make command for Ngspice + ''' print("run Make Called") self.release_home = self.parser.get('NGHDL', 'RELEASE') path_icm = os.path.join(self.release_home, "src/xspice/icm") @@ -965,10 +997,11 @@ and set the load for input ports */ os.chdir(self.cur_dir) except BaseException: print("There is error in 'make' ") - # sys.exit() - # Running the make install command for Ngspice def runMakeInstall(self): + ''' + Running the make install command for Ngspice + ''' self.cur_dir = os.getcwd() print("run Make Install Called") self.release_home = self.parser.get('NGHDL', 'RELEASE') @@ -1005,11 +1038,12 @@ and set the load for input ports */ except BaseException as e: print(e) print("There is error in 'make install' ") - # sys.exit() - # This function is used to add additional files required by the verilog - # top module def addfile(self): + ''' + This function is used to add additional files + required by the verilog top module. + ''' print("Adding the files required by the top level module file") init_path = '../../' @@ -1120,9 +1154,11 @@ and set the load for input ports */ print("Added the folder") # os.chdir(self.cur_dir) - # This function is used to print the titles in the terminal of Ngveri tab def termtitle(self, textin): - + ''' + This function is used to print the titles + in the terminal of Ngveri tab. + ''' Text = "<span style=\" font-size:20pt; \ font-weight:1000; color:#0000FF;\" >" Text += "<br>================================<br>" @@ -1131,20 +1167,23 @@ and set the load for input ports */ Text += "</span>" self.termedit.append(Text) - # This function is used to print the text/commands in the terminal of - # Ngveri tab def termtext(self, textin): - + ''' + This function is used to print the text/commands + in the terminal of Ngveri tab. + ''' Text = "<span style=\" font-size:12pt;\ font-weight:500; color:#000000;\" >" Text += textin Text += "</span>" self.termedit.append(Text) - # This function reads all the Standard output data and the errors from the - # process that aree being run @QtCore.pyqtSlot() def readAllStandard(self): + ''' + This function reads all the standard output data and + the errors from the process that are being run. + ''' # self.termedit = termedit # self.termedit.append(str(self.process.readAll().data(),\ # encoding='utf-8')) @@ -1166,11 +1205,12 @@ and set the load for input ports */ TextErr += "<br>" + line TextErr += "</span>" self.termedit.append(TextErr) + # @QtCore.pyqtSlot() # def readAllStandard(self): # #self.termedit = termedit # self.termedit.append(str(self.process.\ - # readAll().data(), encoding='utf-8')) + # readAll().data(), encoding='utf-8')) # print(str(self.process.readAll().data(), encoding='utf-8')) # stderror = self.process.readAllStandardError() @@ -1183,32 +1223,32 @@ and set the load for input ports */ # Text += "</span>" # self.termedit.append(Text+"\n") - # init_path = '../../' - # if os.name == 'nt': - # init_path = '' - # includefile = QtCore.QDir.toNativeSeparators(\ - # QtWidgets.QFileDialog.getOpenFileName( - # self, "Open adding other necessary files to be included", - # init_path + "home" - # )[0] - # ) - # if includefile=="": - # reply=QtWidgets.QMessageBox.critical( - # None, "Error Message", - # "<b>Error: No File Chosen. Please chose a file</b>", - # QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel - # ) - # if reply == QtWidgets.QMessageBox.Ok: - # self.addfile() - # self.obj_Appconfig.print_info('Add Other Files Called') - - # elif reply == QtWidgets.QMessageBox.Cancel: - # self.obj_Appconfig.print_info('No File Chosen') - # filename = os.path.basename(includefile) - # self.modelpath=self.digital_home+"/"+self.fname.split('.')[0]+"/" - - # if not os.path.isdir(self.modelpath): - # os.mkdir(self.modelpath) - # text = open(includefile).read() - # open(self.modelpath+filename,'w').write(text) - # includefile.close() + # init_path = '../../' + # if os.name == 'nt': + # init_path = '' + # includefile = QtCore.QDir.toNativeSeparators(\ + # QtWidgets.QFileDialog.getOpenFileName( + # self, "Open adding other necessary files to be included", + # init_path + "home" + # )[0] + # ) + # if includefile=="": + # reply=QtWidgets.QMessageBox.critical( + # None, "Error Message", + # "<b>Error: No File Chosen. Please chose a file</b>", + # QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel + # ) + # if reply == QtWidgets.QMessageBox.Ok: + # self.addfile() + # self.obj_Appconfig.print_info('Add Other Files Called') + + # elif reply == QtWidgets.QMessageBox.Cancel: + # self.obj_Appconfig.print_info('No File Chosen') + # filename = os.path.basename(includefile) + # self.modelpath=self.digital_home+"/"+self.fname.split('.')[0]+"/" + + # if not os.path.isdir(self.modelpath): + # os.mkdir(self.modelpath) + # text = open(includefile).read() + # open(self.modelpath+filename,'w').write(text) + # includefile.close() diff --git a/src/maker/NgVeri.py b/src/maker/NgVeri.py index 4a221964..c5756e7d 100755 --- a/src/maker/NgVeri.py +++ b/src/maker/NgVeri.py @@ -37,10 +37,10 @@ from configuration.Appconfig import Appconfig from configparser import ConfigParser -# beginning class NgVeri. This class create the NgVeri Tab class NgVeri(QtWidgets.QWidget): - - # initialising the variables + ''' + This class create the NgVeri Tab + ''' def __init__(self, filecount): QtWidgets.QWidget.__init__(self) # Maker.addverilog(self) @@ -67,10 +67,10 @@ class NgVeri(QtWidgets.QWidget): self.fname = "" self.filecount = filecount - # Creating the various components of the Widget(Ngveri Tab) - def createNgveriWidget(self): - + ''' + Creating the various components of the Widget(Ngveri Tab) + ''' self.grid = QtWidgets.QGridLayout() self.setLayout(self.grid) @@ -79,8 +79,10 @@ class NgVeri(QtWidgets.QWidget): self.show() - # Adding the verilog file in Maker tab to Ngveri Tab automatically def addverilog(self): + ''' + Adding the verilog file in Maker tab to Ngveri Tab automatically + ''' # b=Maker.Maker(self) print(Maker.verilogFile) if Maker.verilogFile[self.filecount] == "": @@ -194,9 +196,11 @@ class NgVeri(QtWidgets.QWidget): # model.verilogfile() model.addfile() - # This function is used to add additional folder required by the verilog - # top module def addfolder(self): + ''' + This function is used to add additional folder required + by the verilog top module. + ''' if len(Maker.verilogFile) < (self.filecount + 1): reply = QtWidgets.QMessageBox.critical( None, @@ -214,14 +218,16 @@ class NgVeri(QtWidgets.QWidget): # model.verilogfile() model.addfolder() - # This function is used to clear the terminal - def clearTerminal(self): + ''' + This function is used to clear the terminal + ''' self.entry_var[0].setText("") - # This function is used to create buttons/options def createoptionsBox(self): - + ''' + This function is used to create buttons/options + ''' self.optionsbox = QtWidgets.QGroupBox() self.optionsbox.setTitle("Select Options") self.optionsgrid = QtWidgets.QGridLayout() @@ -263,9 +269,11 @@ class NgVeri(QtWidgets.QWidget): return self.optionsbox - # This function is used to remove models in modlst of Ngspice folder if - # the user wants to remove a model. Note: files do not get removed def edit_modlst(self, text): + ''' + This is used to remove models in modlst of Ngspice folder if + the user wants to remove a model. Note: files do not get removed. + ''' if text == "Remove Verilog Models": return index = self.entry_var[1].findText(text) @@ -357,11 +365,11 @@ class NgVeri(QtWidgets.QWidget): file.close() self.entry_var[3].setText("") - # creating various other groups like terminal, remove modlst, remove lint_off - # and add lint_off - def creategroup(self): - + ''' + Creates various other groups like terminal, remove modlst, + remove lint_off and add lint_off + ''' self.trbox = QtWidgets.QGroupBox() self.trbox.setTitle("Terminal") # self.trbox.setDisabled(True) diff --git a/src/ngspicetoModelica/NgspicetoModelica.py b/src/ngspicetoModelica/NgspicetoModelica.py index 6951e3c8..9a3d504f 100755 --- a/src/ngspicetoModelica/NgspicetoModelica.py +++ b/src/ngspicetoModelica/NgspicetoModelica.py @@ -998,7 +998,7 @@ class NgMoConverter: for i in range(0, len(words), 1): words[i] = words[i].replace("-", "") - if( + if ( eachline[0] == 'r' or eachline[0] == 'R' or eachline[0] == 'c' or |