📄 spicenum.c
字号:
/* spicenum.c Copyright (C) 2002 Georg Post * * This file is part of Numparam, see: readme.txt * Free software under the terms of the GNU Lesser General Public License *//* number parameter add-on for Spice. to link with mystring.o, xpressn.o (math formula interpreter), and with Spice frontend src/lib/fte.a . Interface function nupa_signal to tell us about automaton states.Buglist (some are 'features'): blank lines get category '*' inserts conditional blanks before or after braces between .control and .endc, flags all lines as 'category C', dont touch. there are reserved magic numbers (1e9 + n) as placeholders control lines must not contain {} . ignores the '.option numparam' line planned to trigger the actions operation of .include certainly doesnt work there are frozen maxima for source and expanded circuit size.Todo: add support for nested .if .elsif .else .endif controls.*/#include <stdio.h>#include <stdlib.h>#ifdef __TURBOC__#include <process.h> /* exit() */#endif#include "general.h"#include "numparam.h"/* Uncomment this line to allow debug tracing *//* #define TRACE_NUMPARAMS *//* the nupa_signal arguments sent from Spice: sig=1: Start of the subckt expansion. sig=2: Stop of the subckt expansion. sig=3: Stop of the evaluation phase. sig=0: Start of a deck copy operation After sig=1 until sig=2, nupa_copy does no transformations. At sig=2, we prepare for nupa_eval loop. After sig=3, we assume the initial state (clean). In Clean state, a lot of deckcopy operations come in and we overwrite any line pointers, or we start a new set after each sig=0 ? Anyway, we neutralize all & and .param lines (category[] array!) and we substitute all {} &() and &id placeholders by dummy numbers. The placeholders are long integers 1000000000+n (10 digits, n small).*//********** string handling ***********/#define PlaceHold 1000000000LIntern long placeholder= 0;#ifdef NOT_REQUIRED /* SJB - not required as front-end now does stripping */InternFunc short stripcomment( Pchar s)/* allow end-of-line comments in Spice, like C++ */Begin short i,ls; char c,d; Bool stop; ls=length(s); c=' '; i=0; stop=False; While (i<ls) And Not stop Do d=c; Inc(i); c=s[i-1]; stop=(c==d) And ((c=='/')Or(c=='-')); /* comments after // or -- */ Done If stop Then i=i-2; /*last valid character before Comment */ While (i>0)And (s[i-1]<=' ') Do Dec(i) Done; /*strip blank space*/ If i<=0 Then scopy(s,"") Else pscopy(s,s,1,i) EndIf Else i= -1 EndIf return i /* i>=0 if comment stripped at that position */EndFunc#endif /* NOT_REQUIRED */InternProc stripsomespace(Pchar s, Bool incontrol)Begin/* iff s starts with one of some markers, strip leading space */ Str(12,markers); short i,ls; scopy(markers,"*.&+#$"); If Not incontrol Then sadd(markers,"xX") EndIf ls=length(s); i=0; While (i<ls) And (s[i]<=' ') Do Inc(i) Done If (i>0) And (i<ls) And (cpos(s[i],markers) >0) Then pscopy(s,s,i+1,ls) EndIfEndProc#if 0 /* unused? */Proc partition(Pchar t)/* t is a list val=expr val=expr .... Insert Lf-& before any val= *//* the Basic preprocessor doesnt understand multiple cmd/line *//* bug: strip trailing spaces */Begin Strbig(Llen,u); short i,lt,state; char c; cadd(u,Intro); state=0; /* a trivial 3-state machine */ lt=length(t); While t[lt-1] <= ' ' Do Dec(lt) Done For i=0; i<lt; Inc(i) Do c=t[i]; If c=='=' Then state=1 ElsIf (state==1) And (c==' ') Then state=2 EndIf If state==2 Then cadd(u,Lf); cadd(u,Intro); state=0 EndIf cadd(u,c) Done scopy(t,u); For i=0; i<length(t); Inc(i) Do /* kill braces inside */ If (t[i]=='{') Or (t[i]=='}') Then t[i]=' ' EndIf DoneEndProc#endifInternFunc short stripbraces( Pchar s)/* puts the funny placeholders. returns the number of {...} substitutions */Begin short n,i,nest,ls,j; Strbig(Llen,t); n=0; ls=length(s); i=0; While i<ls Do If s[i]=='{' Then /* something to strip */ j= i+1; nest=1; Inc(n); While (nest>0) And (j<ls) Do If s[j]=='{' Then Inc(nest) ElsIf s[j]=='}' Then Dec(nest) EndIf Inc(j) Done pscopy(t,s,1,i); Inc(placeholder); If t[i-1]>' ' Then cadd(t,' ') EndIf nadd(t, PlaceHold + placeholder); If s[j]>=' ' Then cadd(t,' ') EndIf i=length(t); pscopy(s,s, j+1, ls); sadd(t,s); scopy(s,t); Else Inc(i) EndIf ls=length(s) Done return nEndFuncIntern Func short findsubname(tdico * dico, Pchar s)/* truncate the parameterized subckt call to regular old Spice *//* scan a string from the end, skipping non-idents and {expressions} *//* then truncate s after the last subckt(?) identifier */Begin Str(80, name); short h,j,k,nest,ls; Bool found; h=0; ls=length(s); k=ls; found=False; While (k>=0) And (Not found) Do /* skip space, then non-space */ While (k>=0) And (s[k]<=' ') Do Dec(k) Done; h=k+1; /* at h: space */ While (k>=0) And (s[k]>' ') Do If s[k]=='}' Then nest=1; Dec(k); While (nest>0) And (k>=0) Do If s[k]=='{' Then Dec(nest) ElsIf s[k]=='}' Then Inc(nest) EndIf Dec(k) Done h=k+1; /* h points to '{' */ Else Dec(k) EndIf; Done found = (k>=0) And alfa(s[k+1]); /* suppose an identifier */ If found Then /* check for known subckt name */ scopy(name,""); j= k+1; While alfanum(s[j]) Do cadd(name, upcase(s[j])); Inc(j) Done found= (getidtype(dico, name) == 'U'); EndIf Done If found And (h<ls) Then pscopy(s,s,1,h) EndIf return h;EndFuncInternProc modernizeex( Pchar s)/* old style expressions &(..) and &id --> new style with braces. */Begin Strbig(Llen,t); short i,state, ls; char c,d; i=0; state=0; ls= length(s); While i<ls Do c= s[i]; d=s[i+1]; If Zero(state) And (c==Intro) And (i>0) Then If d=='(' Then state=1; Inc(i); c='{' ElsIf alfa(d) Then cadd(t,'{'); Inc(i); While alfanum(s[i]) Do cadd(t,s[i]); Inc(i) Done c='}'; Dec(i); EndIf ElsIf NotZ(state) Then If c=='(' Then Inc(state) ElsIf c==')' Then Dec(state) EndIf If Zero(state) Then /* replace ) by terminator */ c='}'; EndIf EndIf cadd(t,c); Inc(i) Done scopy(s,t);EndProcInternFunc char transform(tdico * dico, Pchar s, Bool nostripping, Pchar u)/* line s is categorized and crippled down to basic Spice * returns in u control word following dot, if any * * any + line is copied as-is. * any & or .param line is commented-out. * any .subckt line has params section stripped off * any X line loses its arguments after sub-circuit name * any &id or &() or {} inside line gets a 10-digit substitute. * * strip the new syntax off the codeline s, and * return the line category as follows: * '*' comment line * '+' continuation line * ' ' other untouched netlist or command line * 'P' parameter line, commented-out; (name,linenr)-> symbol table. * 'S' subckt entry line, stripped; (name,linenr)-> symbol table. * 'U' subckt exit line * 'X' subckt call line, stripped * 'C' control entry line * 'E' control exit line * '.' any other dot line * 'B' netlist (or .model ?) line that had Braces killed */Begin Strbig(Llen,t); char category; short i,k, a,n;/* i=stripcomment(s); sjb - not required now that front-end does stripping */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -