File indexing completed on 2024-05-19 05:46:25
0001 #include <cmath> 0002 #include <iostream> 0003 0004 #include <QFile> 0005 #include <QRegExp> 0006 #include <QString> 0007 #include <QStringList> 0008 0009 using namespace std; 0010 0011 const int minPrefixExp = -24; 0012 const int maxPrefixExp = 24; 0013 const int numPrefix = int((maxPrefixExp - minPrefixExp) / 3) + 1; 0014 const QString SIprefix[] = {"y", "z", "a", "f", "p", "n", QChar(0xB5), "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"}; 0015 0016 /** 0017 * Converts a number string (including an optional SI suffix) to a real number. 0018 */ 0019 double toReal(QString text); 0020 0021 const QString inputFile = "spicemodels_bipolar_transistors.txt"; 0022 const QString outputFile = "output.lib"; 0023 0024 #define setProperty(property, value) outputStream << QString("%1=%2\n").arg(property).arg(value) 0025 0026 int main() 0027 { 0028 QFile input(inputFile); 0029 if (!input.open(QIODevice::ReadOnly)) { 0030 cerr << "Could not open input file \"" << inputFile << "\" for reading.\n"; 0031 return 1; 0032 } 0033 0034 QFile output(outputFile); 0035 if (!output.open(QIODevice::WriteOnly)) { 0036 cerr << "Could not open output file \"" << outputFile << "\" for writing.\n"; 0037 return 1; 0038 } 0039 0040 QTextStream inputStream(&input); 0041 QTextStream outputStream(&output); 0042 0043 QStringList IDs; 0044 0045 // Set true inside the while loop so when we come across a new model 0046 // in the input file, we can close the previous one in the output file. 0047 bool modelOpen = false; 0048 0049 while (!inputStream.atEnd()) { 0050 QString line = inputStream.readLine(); 0051 0052 // Make life easier 0053 line.replace(QRegExp("\\.MODEL[^(]*\\("), "+ "); 0054 line.remove(")"); 0055 0056 if (line.isEmpty()) 0057 continue; 0058 0059 if (line.startsWith("*SRC=")) { 0060 if (modelOpen) 0061 outputStream << "[/]\n\n"; 0062 modelOpen = true; 0063 0064 line.remove(0, 5); // remove "*SRC=" 0065 0066 QStringList segments = line.split(';'); // QStringList::split( ';', line ); // 2018.12.01 0067 if (segments.size() != 5) { 0068 cerr << "Wrong number of \";\" for line \"" << line.latin1() << "\".\n"; 0069 continue; 0070 } 0071 0072 QStringList::iterator segmentsEnd = segments.end(); 0073 for (QStringList::iterator it = segments.begin(); it != segmentsEnd; ++it) 0074 *it = (*it).trimmed(); 0075 0076 QString ID = segments[0]; 0077 outputStream << QString("[%1]\n").arg(ID); 0078 if (IDs.contains(ID)) { 0079 cerr << "Already have ID \"" << ID << "\".\n"; 0080 continue; 0081 } else 0082 IDs.append(ID); 0083 0084 if (segments[2] == "BJTs PNP") 0085 setProperty("Type", "PNP"); 0086 else if (segments[2] == "BJTs NPN") 0087 setProperty("Type", "NPN"); 0088 else 0089 cerr << "Unknown type \"" << segments[2] << "\".\n"; 0090 0091 setProperty("Description", segments[4]); 0092 } 0093 0094 else if (line.startsWith("+ ")) { 0095 line.remove(0, 2); // remove "+ ": 0096 QRegExp rx("([^\\s=]*)=([^\\s]*)"); 0097 0098 int pos = 0; 0099 while ((pos = rx.search(line, pos)) >= 0) { 0100 QString property = rx.cap(1); 0101 QString value = rx.cap(2); 0102 0103 setProperty(property, toReal(value)); 0104 0105 pos += 4; // avoid the string we just found 0106 } 0107 } 0108 0109 else 0110 cerr << "Unknown line for line \"" << line.latin1() << "\".\n"; 0111 } 0112 0113 // And the final closing brace 0114 if (modelOpen) 0115 outputStream << "[/]\n\n"; 0116 0117 input.close(); 0118 output.close(); 0119 0120 return 0; 0121 } 0122 0123 double getMultiplier(QString mag) 0124 { 0125 if (mag.isEmpty()) 0126 return 1.0; 0127 0128 // Allow the user to enter in "u" instead of mu 0129 if (mag == "u") 0130 mag = QChar(0xB5); 0131 0132 for (int i = 0; i < numPrefix; ++i) { 0133 if (mag == SIprefix[i]) 0134 return pow(10., (i * 3) + minPrefixExp); 0135 } 0136 0137 // default 0138 return 1.0; 0139 } 0140 0141 double toReal(QString text) 0142 { 0143 if (text.isEmpty()) { 0144 cerr << "Attempted to convert empty text to number.\n"; 0145 return 0.0; 0146 } 0147 0148 // Extract the possible SI suffix 0149 QChar suffix = text[text.length() - 1]; 0150 double multiplier = 1.0; 0151 if (suffix.isLetter()) { 0152 multiplier = getMultiplier(QString(suffix)); 0153 text.remove(text.length() - 1, 1); 0154 } 0155 0156 bool ok; 0157 double val = text.toDouble(&ok); 0158 0159 if (!ok) { 0160 cerr << "Could not convert number string \"" << text << "\" to real.\n"; 0161 return 0.0; 0162 } 0163 0164 return val * multiplier; 0165 }