lspc.red 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. module lspc; %% GENTRAN LISP-to-C Translation Module %%
  2. %% Author: Barbara L. Gates %%
  3. %% December 1986 %%
  4. % Entry Point: CCode
  5. symbolic$
  6. fluid '(!*double !*gendecs)$
  7. switch gendecs$
  8. % User-Accessible Global Variables %
  9. global '(clinelen!* minclinelen!* !*ccurrind!* ccurrind!* tablen!*)$
  10. share clinelen!*, minclinelen!*, ccurrind!*, tablen!*$
  11. ccurrind!* := 0$
  12. clinelen!* := 80$
  13. minclinelen!* := 40$
  14. !*ccurrind!* := 0$ %current level of indentation for C code
  15. global '(deftype!* !*c!-functions!*)$
  16. global '(!*posn!* !$!#);
  17. !*c!-functions!* := '(sin cos tan asin acos atan atan2 sinh cosh tanh
  18. asinh acosh atanh sincos sinpi cospi tanpi asinpi
  19. acospi atanpi exp expm1 exp2 exp10 log log1p log2
  20. log10 pow compound annuity abs fabs fmod sqrt
  21. cbrt)$
  22. flag( '(abs),'!*int!-args!*)$ % Intrinsic function with integer arg.
  23. %% %%
  24. %% LISP-to-C Translation Functions %%
  25. %% %%
  26. put('c,'formatter,'formatc);
  27. put('c,'codegen,'ccode);
  28. put('c,'proctem,'procctem);
  29. put('c,'gendecs,'cdecs);
  30. put('c,'assigner,'mkfcassign);
  31. put('c,'boolean!-type,'!i!n!t);
  32. %% Control Function %%
  33. symbolic procedure ccode forms;
  34. for each f in forms conc
  35. if atom f then
  36. cexp f
  37. else if car f memq '(!:rd!: !:cr!: !:crn!: !:gi!:) then
  38. cexp f
  39. else if lispstmtp f or lispstmtgpp f then
  40. if !*gendecs then
  41. begin
  42. scalar r;
  43. r := append(cdecs symtabget('!*main!*, '!*decs!*),
  44. cstmt f);
  45. symtabrem('!*main!*, '!*decs!*);
  46. return r
  47. end
  48. else
  49. cstmt f
  50. else if lispdefp f then
  51. cproc f
  52. else
  53. cexp f$
  54. %% Procedure Translation %%
  55. symbolic procedure cproc deff; % Type details amended mcd 3/3/88
  56. begin
  57. scalar type, name, params, paramtypes, vartypes, body, r;
  58. name := cadr deff;
  59. if onep length (body := cdddr deff) and lispstmtgpp car body then
  60. << body := cdar body; if null car body then body := cdr body >>;
  61. if (type := symtabget(name, name)) then
  62. << type := cadr type;
  63. % Convert reduce types to c types
  64. if type equal 'real then
  65. type := '!f!l!o!a!t
  66. else if type equal 'integer then
  67. type := '!i!n!t;
  68. if !*double then
  69. if type equal '!f!l!o!a!t then
  70. type := '!d!o!u!b!l!e
  71. else if type equal '!i!n!t then
  72. type := '!l!o!n!g;
  73. symtabrem(name, name)
  74. >>;
  75. params := symtabget(name, '!*params!*) or caddr deff;
  76. symtabrem(name, '!*params!*);
  77. for each dec in symtabget(name, '!*decs!*) do
  78. if car dec memq params
  79. then paramtypes := append(paramtypes, list dec)
  80. else vartypes := append(vartypes, list dec);
  81. r := append( append( mkfcprocdec(type, name, params),
  82. cdecs paramtypes ),
  83. mkfcbegingp() );
  84. indentclevel(+1);
  85. if !*gendecs then
  86. r := append(r, cdecs vartypes);
  87. r := append(r, for each s in body
  88. conc cstmt s);
  89. indentclevel(-1);
  90. r := append(r, mkfcendgp());
  91. if !*gendecs then
  92. << symtabrem(name, nil); symtabrem(name, '!*decs!*) >>;
  93. return r
  94. end$
  95. %% Generation of Declarations %%
  96. symbolic procedure cdecs decs;
  97. for each tl in formtypelists decs
  98. conc mkfcdec(car tl, cdr tl)$
  99. %% Expression Translation %%
  100. symbolic procedure cexp exp;
  101. cexp1(exp, 0)$
  102. symbolic procedure cexp1(exp, wtin);
  103. if atom exp then
  104. list cname exp
  105. else
  106. if onep length exp then
  107. append(cname exp, insertparens(()))
  108. else if car exp eq 'expt then
  109. if caddr exp = 2 then
  110. cexp1 (list('times, cadr exp, cadr exp), wtin)
  111. else if caddr exp = 3 then
  112. cexp1 (list('times, cadr exp, cadr exp, cadr exp), wtin)
  113. else if caddr exp = 4 then
  114. cexp1(list('times,cadr exp,cadr exp,cadr exp,cadr exp),wtin)
  115. else if caddr exp = '(quotient 1 2) then
  116. cexp1 (list('sqrt, cadr exp), wtin)
  117. else
  118. cexp1 ('pow . cdr exp,wtin)
  119. else if optype car exp then
  120. begin
  121. scalar wt, op, res;
  122. wt := cprecedence car exp;
  123. op := cop car exp;
  124. exp := cdr exp;
  125. if onep length exp then
  126. res := op . cexp1(car exp, wt)
  127. else
  128. <<
  129. res := cexp1(car exp, wt);
  130. if op eq '!+ then
  131. while exp := cdr exp do
  132. <<
  133. if atom car exp or caar exp neq 'minus then
  134. res := append(res, list op);
  135. res := append(res, cexp1(car exp, wt))
  136. >>
  137. else
  138. while exp := cdr exp do
  139. res := append(append(res, list op),
  140. cexp1(car exp, wt))
  141. >>;
  142. if wtin >= wt then res := insertparens res;
  143. return res
  144. end
  145. else if car exp eq 'literal then
  146. cliteral exp
  147. else if car exp eq 'range then
  148. if cadr exp = 0 then cexp caddr exp
  149. else gentranerr('e,exp,
  150. "C does not support non-zero lower bounds",nil)
  151. else if car exp eq '!:rd!: then
  152. if smallfloatp cdr exp then
  153. list cdr exp
  154. else
  155. begin scalar mt; % Print bigfloats more naturally.
  156. integer dotpos,!:lower!-sci!:,!:upper!-sci!:;
  157. % This forces most numbers to exponential format.
  158. mt := rd!:explode exp;
  159. exp := car mt;
  160. mt := cadr mt + caddr mt - 1;
  161. exp := append(list('literal,car exp, '!.),cdr exp);
  162. if null (mt = 0) then
  163. exp := append(exp,
  164. list('!e,mt));
  165. return cliteral exp;
  166. end
  167. else if car exp memq '(!:cr!: !:crn!: !:gi!:) then
  168. gentranerr('e,exp,"C doesn't support complex data type",nil)
  169. else if arrayeltp exp then
  170. cname car exp . foreach s in cdr exp conc
  171. insertbrackets cexp1(s, 0)
  172. else if memq(car exp,!*c!-functions!*) then
  173. begin scalar op,res,dblp;
  174. dblp := not get(car exp,'!*int!-args!*);
  175. op := cname car exp;
  176. res := '!( . list op ;
  177. while exp := cdr exp do
  178. <<
  179. op := cexp1(car exp, 0);
  180. if dblp and not
  181. (is!-c!-float(op) or is!-c!-float(car exp)) then
  182. op := if fixp car op then
  183. (float car op) . (cdr op)
  184. else
  185. append(list('!(,'!d!o!u!b!l!e,'!),'!(),
  186. append(op,list '!)));
  187. res := if cdr exp then
  188. append('!, . reversip op,res)
  189. else
  190. append(reversip op,res);
  191. >>;
  192. return reversip ( '!) . res )
  193. end
  194. else if cfunctcallp exp then
  195. begin
  196. scalar op, res;
  197. op := cname car exp;
  198. exp := cdr exp;
  199. res := '!( . cexp1(car exp, 0);
  200. while exp := cdr exp do
  201. res := append(res, '!, . cexp1(car exp, 0));
  202. return op . append(res, list('!)) )
  203. end
  204. else
  205. begin
  206. scalar op, res;
  207. op := cname car exp;
  208. exp := cdr exp;
  209. res := append( '![ . cexp1(car exp, 0),list('!]) );
  210. % Changed to generate proper C arrays - mcd 25/9/89
  211. while exp := cdr exp do
  212. res := append(res, append('![ . cexp1(car exp, 0)
  213. ,list('!]) ) );
  214. return op . res
  215. end$
  216. symbolic procedure string2id str;
  217. intern compress reversip cdr reversip cdr explode str$
  218. symbolic procedure is!-c!-float u;
  219. % Returns T if u is a float or a list whose car is an intrinsic
  220. % function name with a floating point result.
  221. floatp(u) or (idp u and declared!-as!-float(u) ) or
  222. pairp(u) and (car u eq '!:rd!: or
  223. stringp car u and memq(string2id car u,!*c!-functions!*) and
  224. not flagp(string2id car u, '!*int!-args!*) or
  225. declared!-as!-float(car u) )$
  226. symbolic procedure cfunctcallp exp;
  227. symtabget(car exp,'!*type!*)$
  228. symbolic procedure cop op;
  229. get(op, '!*cop!*) or op$
  230. put('or, '!*cop!*, '!|!|)$
  231. put('and, '!*cop!*, '!&!&)$
  232. put('not, '!*cop!*, '!! )$
  233. put('equal, '!*cop!*, '!=!=)$
  234. put('neq, '!*cop!*, '!!!=)$
  235. put('greaterp, '!*cop!*, '> )$
  236. put('geq, '!*cop!*, '!>!=)$
  237. put('lessp, '!*cop!*, '< )$
  238. put('leq, '!*cop!*, '!<!=)$
  239. put('plus, '!*cop!*, '!+ )$
  240. put('times, '!*cop!*, '* )$
  241. put('quotient, '!*cop!*, '/ )$
  242. put('minus, '!*cop!*, '!- )$
  243. symbolic procedure cname a;
  244. if stringp a then
  245. stringtoatom a % convert a to atom containing "'s
  246. else if memq(a,!*c!-functions!*) then
  247. string!-downcase a
  248. else
  249. get(a, '!*cname!*) or a$
  250. symbolic procedure cprecedence op;
  251. get(op, '!*cprecedence!*) or 8$
  252. put('or, '!*cprecedence!*, 1)$
  253. put('and, '!*cprecedence!*, 2)$
  254. put('equal, '!*cprecedence!*, 3)$
  255. put('neq, '!*cprecedence!*, 3)$
  256. put('greaterp, '!*cprecedence!*, 4)$
  257. put('geq, '!*cprecedence!*, 4)$
  258. put('lessp, '!*cprecedence!*, 4)$
  259. put('leq, '!*cprecedence!*, 4)$
  260. put('plus, '!*cprecedence!*, 5)$
  261. put('times, '!*cprecedence!*, 6)$
  262. put('quotient, '!*cprecedence!*, 6)$
  263. put('not, '!*cprecedence!*, 7)$
  264. put('minus, '!*cprecedence!*, 7)$
  265. %% Statement Translation %%
  266. symbolic procedure cstmt stmt;
  267. if null stmt then
  268. nil
  269. else if lisplabelp stmt then
  270. clabel stmt
  271. else if car stmt eq 'literal then
  272. cliteral stmt
  273. else if lispassignp stmt then
  274. cassign stmt
  275. else if lispcondp stmt then
  276. cif stmt
  277. else if lispbreakp stmt then
  278. cbreak stmt
  279. else if lispgop stmt then
  280. cgoto stmt
  281. else if lispreturnp stmt then
  282. creturn stmt
  283. else if lispstopp stmt then
  284. cexit stmt
  285. else if lisprepeatp stmt then
  286. crepeat stmt
  287. else if lispwhilep stmt then
  288. cwhile stmt
  289. else if lispforp stmt then
  290. cfor stmt
  291. else if lispstmtgpp stmt then
  292. cstmtgp stmt
  293. else if lispdefp stmt then
  294. cproc stmt
  295. else
  296. cexpstmt stmt$
  297. symbolic procedure cassign stmt;
  298. mkfcassign(cadr stmt, caddr stmt)$
  299. symbolic procedure cbreak stmt;
  300. mkfcbreak()$
  301. symbolic procedure cexit stmt;
  302. mkfcexit()$
  303. symbolic procedure cexpstmt exp;
  304. append(mkctab() . cexp exp, list('!;, mkcterpri()))$
  305. symbolic procedure cfor stmt;
  306. begin
  307. scalar r, var, loexp, stepexp, hiexp, stmtlst;
  308. var := cadr stmt;
  309. stmt := cddr stmt;
  310. loexp := caar stmt;
  311. stepexp := cadar stmt;
  312. hiexp := caddar stmt;
  313. stmtlst := cddr stmt;
  314. r := mkfcfor(var, loexp,
  315. list(if (numberp stepexp and stepexp < 0) or
  316. eqcar(stepexp,'minus) then 'geq else 'leq,
  317. var, hiexp),
  318. var,
  319. list('plus, var, stepexp));
  320. indentclevel(+1);
  321. r := append(r, foreach st in stmtlst conc cstmt st);
  322. indentclevel(-1);
  323. return r
  324. end$
  325. symbolic procedure cgoto stmt;
  326. mkfcgo cadr stmt$
  327. symbolic procedure cif stmt;
  328. begin
  329. scalar r, st;
  330. r := mkfcif caadr stmt;
  331. indentclevel(+1);
  332. st := seqtogp cdadr stmt;
  333. if eqcar(st, 'cond) and length st=2 then
  334. st := mkstmtgp(0, list st);
  335. r := append(r, cstmt st);
  336. indentclevel(-1);
  337. stmt := cdr stmt;
  338. while (stmt := cdr stmt) and caar stmt neq t do
  339. <<
  340. r := append(r, mkfcelseif caar stmt);
  341. indentclevel(+1);
  342. st := seqtogp cdar stmt;
  343. if eqcar(st, 'cond) and length st=2 then
  344. st := mkstmtgp(0, list st);
  345. r := append(r, cstmt st);
  346. indentclevel(-1)
  347. >>;
  348. if stmt then
  349. <<
  350. r := append(r, mkfcelse());
  351. indentclevel(+1);
  352. st := seqtogp cdar stmt;
  353. if eqcar(st, 'cond) and length st=2 then
  354. st := mkstmtgp(0, list st);
  355. r := append(r, cstmt st);
  356. indentclevel(-1)
  357. >>;
  358. return r
  359. end$
  360. symbolic procedure clabel label;
  361. mkfclabel label$
  362. symbolic procedure cliteral stmt;
  363. mkfcliteral cdr stmt$
  364. symbolic procedure crepeat stmt;
  365. begin
  366. scalar r, stmtlst, logexp;
  367. stmt := reverse cdr stmt;
  368. logexp := car stmt;
  369. stmtlst := reverse cdr stmt;
  370. r := mkfcdo();
  371. indentclevel(+1);
  372. r := append(r, foreach st in stmtlst conc cstmt st);
  373. indentclevel(-1);
  374. return append(r, mkfcdowhile list('not, logexp))
  375. end$
  376. symbolic procedure creturn stmt;
  377. if cdr stmt then
  378. mkfcreturn cadr stmt
  379. else
  380. mkfcreturn nil$
  381. symbolic procedure cstmtgp stmtgp;
  382. begin
  383. scalar r;
  384. if car stmtgp eq 'progn then
  385. stmtgp := cdr stmtgp
  386. else
  387. stmtgp :=cddr stmtgp;
  388. r := mkfcbegingp();
  389. indentclevel(+1);
  390. r := append(r, for each stmt in stmtgp conc cstmt stmt);
  391. indentclevel(-1);
  392. return append(r, mkfcendgp())
  393. end$
  394. symbolic procedure cwhile stmt;
  395. begin
  396. scalar r, logexp, stmtlst;
  397. logexp := cadr stmt;
  398. stmtlst := cddr stmt;
  399. r := mkfcwhile logexp;
  400. indentclevel(+1);
  401. r := append(r, foreach st in stmtlst conc cstmt st);
  402. indentclevel(-1);
  403. return r
  404. end$
  405. %% %%
  406. %% C Code Formatting Functions %%
  407. %% %%
  408. %% Statement Formatting %%
  409. % A macro used to prevent things with *cname*
  410. % properties being evaluated in certain circumstances. MCD 28.3.94
  411. symbolic smacro procedure cexp_name(u);
  412. if atom u then list(u)
  413. else rplaca(cexp ('dummyArrayToken . cdr u), car u)$
  414. symbolic procedure mkfcassign(lhs, rhs);
  415. begin
  416. scalar st;
  417. if length rhs = 3 and lhs member rhs then
  418. begin
  419. scalar op, exp1, exp2;
  420. op := car rhs;
  421. exp1 := cadr rhs;
  422. exp2 := caddr rhs;
  423. if op = 'plus then
  424. if onep exp1 or onep exp2 then
  425. st := ('!+!+ . cexp_name lhs)
  426. else if exp1 member '(-1 (minus 1))
  427. or exp2 member '(-1 (minus 1)) then
  428. st := ('!-!- . cexp_name lhs)
  429. else if eqcar(exp1, 'minus) then
  430. st := append(cexp_name lhs, '!-!= . cexp cadr exp1)
  431. else if eqcar(exp2, 'minus) then
  432. st := append(cexp_name lhs, '!-!= . cexp cadr exp2)
  433. else if exp1 = lhs then
  434. st := append(cexp_name lhs, '!+!= . cexp exp2)
  435. else
  436. st := append(cexp_name lhs, '!+!= . cexp exp1)
  437. else if op = 'difference and onep exp2 then
  438. st := ('!-!- . cexp_name lhs)
  439. else if op = 'difference and exp1 = lhs then
  440. st := append(cexp_name lhs, '!-!= . cexp exp2)
  441. else if op = 'times and exp1 = lhs then
  442. st := append(cexp_name lhs, '!*!= . cexp exp2)
  443. else if op = 'times then
  444. st := append(cexp_name lhs, '!*!= . cexp exp1)
  445. else if op = 'quotient and exp1 = lhs then
  446. st := append(cexp_name lhs, '!/!= . cexp exp2)
  447. else
  448. st := append(cexp_name lhs, '!= . cexp rhs)
  449. end
  450. else
  451. st := append(cexp_name lhs, '!= . cexp rhs);
  452. return append(mkctab() . st, list('!;, mkcterpri()))
  453. end$
  454. symbolic procedure mkfcbegingp;
  455. list(mkctab(), '!{, mkcterpri())$
  456. symbolic procedure mkfcbreak;
  457. list(mkctab(), '!b!r!e!a!k, '!;, mkcterpri())$
  458. symbolic procedure mkfcdec(type, varlist); %Amended mcd 13/11/87,3/3/88
  459. <<
  460. if type equal 'scalar then
  461. type := deftype!*;
  462. % Convert Reduce types to C types.
  463. if type equal 'real then
  464. type := '!f!l!o!a!t
  465. else if type equal 'integer then
  466. type := '!i!n!t;
  467. % Deal with precision.
  468. if !*double then
  469. if type equal '!f!l!o!a!t then
  470. type := '!d!o!u!b!l!e
  471. else if type equal '!i!n!t then
  472. type := '!l!o!n!g;
  473. varlist := for each v in varlist collect
  474. if atom v then
  475. v
  476. else
  477. car v . for each dim in cdr v collect
  478. if dim eq 'times then '! %
  479. else if numberp dim then add1 dim
  480. else if eqcar (dim, 'range) and cadr dim = 0
  481. then add1 caddr dim
  482. else gentranerr('e,dim,"Not C dimension",nil);
  483. append(mkctab() . type . '! . for each v in insertcommas varlist
  484. conc cexp_name v,
  485. list('!;, mkcterpri()))
  486. >>$
  487. symbolic procedure mkfcdo;
  488. list(mkctab(), '!d!o, mkcterpri())$
  489. symbolic procedure mkfcdowhile exp;
  490. append(append(list(mkctab(), '!w!h!i!l!e, '! , '!(), cexp exp),
  491. list('!), '!;, mkcterpri()))$
  492. symbolic procedure mkfcelse;
  493. list(mkctab(), '!e!l!s!e, mkcterpri())$
  494. symbolic procedure mkfcelseif exp;
  495. append(append(list(mkctab(), '!e!l!s!e, '! , '!i!f, '! , '!(),
  496. cexp exp),
  497. list('!), mkcterpri()))$
  498. symbolic procedure mkfcendgp;
  499. list(mkctab(), '!}, mkcterpri())$
  500. symbolic procedure mkfcexit;
  501. list(mkctab(), '!e!x!i!t, '!(, 0, '!), '!;, mkcterpri())$
  502. symbolic procedure mkfcfor(var1, lo, cond, var2, nextexp);
  503. <<
  504. if var1 then
  505. var1 := append(cexp var1, '!= . cexp lo);
  506. if cond then
  507. cond := cexp cond;
  508. if var2 then
  509. <<
  510. var2 := cdr mkfcassign(var2, nextexp);
  511. var2 := reverse cddr reverse var2
  512. >>;
  513. append(append(append(list(mkctab(), '!f!o!r! , '! , '!(), var1),
  514. '!; . cond),
  515. append('!; . var2, list('!), mkcterpri())))
  516. >>$
  517. symbolic procedure mkfcgo label;
  518. list(mkctab(), '!g!o!t!o, '! , label, '!;, mkcterpri())$
  519. symbolic procedure mkfcif exp;
  520. append(append(list(mkctab(), '!i!f, '! , '!(), cexp exp),
  521. list('!), mkcterpri()))$
  522. symbolic procedure mkfclabel label;
  523. list(label, '!:, mkcterpri())$
  524. symbolic procedure mkfcliteral args;
  525. for each a in args conc
  526. if a eq 'tab!* then
  527. list mkctab()
  528. else if a eq 'cr!* then
  529. list mkcterpri()
  530. else if pairp a then
  531. cexp a
  532. else
  533. list stripquotes a$
  534. symbolic procedure mkfcprocdec(type, name, params);
  535. <<
  536. params := append('!( . for each p in insertcommas params
  537. conc cexp p,
  538. list '!));
  539. if type then
  540. append(mkctab() . type . '! . cexp name,
  541. append(params,list mkcterpri()))
  542. else
  543. append(mkctab() . cexp name, append(params, list mkcterpri()))
  544. >>$
  545. symbolic procedure mkfcreturn exp;
  546. if exp then
  547. append(append(list(mkctab(), '!r!e!t!u!r!n, '!(), cexp exp),
  548. list('!), '!;, mkcterpri()))
  549. else
  550. list(mkctab(), '!r!e!t!u!r!n, '!;, mkcterpri())$
  551. symbolic procedure mkfcwhile exp;
  552. append(append(list(mkctab(), '!w!h!i!l!e, '! , '!(), cexp exp),
  553. list('!), mkcterpri()))$
  554. %% Indentation Control %%
  555. symbolic procedure mkctab;
  556. list('ctab, ccurrind!*)$
  557. symbolic procedure indentclevel n;
  558. ccurrind!* := ccurrind!* + n * tablen!*$
  559. symbolic procedure mkcterpri;
  560. list 'cterpri$
  561. %% %%
  562. %% Misc. Functions %%
  563. %% %%
  564. symbolic procedure insertbrackets exp;
  565. '![ . append(exp, list '!])$
  566. %% C Code Formatting & Printing Functions %%
  567. symbolic procedure formatc lst;
  568. begin
  569. scalar linelen;
  570. linelen := linelength 300;
  571. !*posn!* := 0;
  572. for each elt in lst do
  573. if pairp elt then lispeval elt
  574. else
  575. <<
  576. if !*posn!* + length explode2 elt > clinelen!* then
  577. ccontline();
  578. pprin2 elt
  579. >>;
  580. linelength linelen
  581. end$
  582. symbolic procedure ccontline;
  583. <<
  584. cterpri();
  585. ctab !*ccurrind!*;
  586. pprin2 " "
  587. >>$
  588. symbolic procedure cterpri;
  589. pterpri()$
  590. symbolic procedure ctab n;
  591. <<
  592. !*ccurrind!* := min0(n, clinelen!* - minclinelen!*);
  593. if (n := !*ccurrind!* - !*posn!*) > 0 then pprin2 nspaces n
  594. >>$
  595. %% C template processing %%
  596. symbolic procedure procctem;
  597. begin
  598. scalar c, linelen;
  599. linelen := linelength 150;
  600. c := readch();
  601. if c eq '!# then c := procc!#line c;
  602. while c neq !$eof!$ do
  603. if c eq !$eol!$ then
  604. c := procc!#line c
  605. else if c eq '!/ then
  606. c := procccomm()
  607. else if c eq '!; then
  608. c := procactive()
  609. else
  610. c := proccheader(c);
  611. linelength linelen
  612. end$
  613. symbolic procedure procc!#line c;
  614. % # ... <cr> %
  615. begin
  616. if c eq !$eol!$ then
  617. << pterpri(); c := readch() >>;
  618. if c eq '!# then
  619. repeat
  620. << pprin2 c; c := readch() >>
  621. until c eq !$eol!$;
  622. return c
  623. end$
  624. symbolic procedure procccomm;
  625. % /* ... */ %
  626. begin
  627. scalar c;
  628. pprin2 '!/;
  629. c := readch();
  630. if c eq '!* then
  631. <<
  632. pprin2 c;
  633. c := readch();
  634. repeat
  635. <<
  636. while c neq '!* do
  637. <<
  638. if c eq !$eol!$
  639. then pterpri()
  640. else pprin2 c;
  641. c := readch()
  642. >>;
  643. pprin2 c;
  644. c := readch()
  645. >>
  646. until c eq '!/;
  647. pprin2 c;
  648. c := readch()
  649. >>;
  650. return c
  651. end$
  652. symbolic procedure proccheader c;
  653. begin
  654. scalar name, i;
  655. while seprp c and c neq !$eol!$ do
  656. << pprin2 c; c := readch() >>;
  657. while not(seprp c or c memq list('!/, '!;, '!()) do
  658. << name := aconc(name, c); pprin2 c; c := readch() >>;
  659. if c memq list(!$eol!$, '!/, '!;) then return c;
  660. while seprp c and c neq !$eol!$ do
  661. << pprin2 c; c := readch() >>;
  662. if c neq '!( then return c;
  663. name := intern compress name;
  664. if not !*gendecs then
  665. symtabput(name, nil, nil);
  666. put('!$0, '!*cname!*, name);
  667. pprin2 c;
  668. i := 1;
  669. c := readch();
  670. while c neq '!) do
  671. <<
  672. while seprp c or c eq '!, do
  673. <<
  674. if c eq !$eol!$
  675. then pterpri()
  676. else pprin2 c;
  677. c := readch()
  678. >>;
  679. name := list c;
  680. pprin2 c;
  681. while not(seprp (c := readch()) or c memq list('!,, '!))) do
  682. << name := aconc(name, c); pprin2 c >>;
  683. put(intern compress append(explode2 '!$, explode2 i),
  684. '!*cname!*,
  685. intern compress name);
  686. i := add1 i;
  687. c:=flushspaces c
  688. >>;
  689. !$!# := sub1 i;
  690. while get(name := intern compress append(explode2 '!$, explode2 i),
  691. '!*cname!*) do
  692. remprop(name, '!*cname!*);
  693. return proccfunction c
  694. end$
  695. symbolic procedure proccfunction c;
  696. begin
  697. scalar !{!}count;
  698. while c neq '!{ do
  699. if c eq '!/ then
  700. c := procccomm()
  701. else if c eq '!; then
  702. c := procactive()
  703. else if c eq !$eol!$ then
  704. << pterpri(); c := readch() >>
  705. else
  706. << pprin2 c; c := readch() >>;
  707. pprin2 c;
  708. !{!}count := 1;
  709. c := readch();
  710. while !{!}count > 0 do
  711. if c eq '!{ then
  712. << !{!}count := add1 !{!}count; pprin2 c; c := readch() >>
  713. else if c eq '!} then
  714. << !{!}count := sub1 !{!}count; pprin2 c; c := readch() >>
  715. else if c eq '!/ then
  716. c := procccomm()
  717. else if c eq '!; then
  718. c := procactive()
  719. else if c eq !$eol!$ then
  720. << pterpri(); c := readch() >>
  721. else
  722. << pprin2 c; c := readch() >>;
  723. return c
  724. end$
  725. endmodule;
  726. end;