STRCONV.MOD 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. IMPLEMENTATION MODULE StrConv;
  2. (*
  3. * REPERTOIRE
  4. * Release 1.6
  5. * By Charles Bradford and Cole Brecheen
  6. * (c) Copyright 1985-1992 PMI
  7. * Green Bay, Wisconsin
  8. * All rights reserved
  9. * (414) 468-6040
  10. *
  11. * $Header: D:/logfiles/mods/strconv.mov 1.7 10 Mar 1991 15:33:12 coleb $
  12. *
  13. *)
  14. IMPORT ErrorManager;
  15. IMPORT Key;
  16. IMPORT LowLevel;
  17. IMPORT M2Strings;
  18. IMPORT Numbers;
  19. IMPORT NumTypes;
  20. IMPORT PosUtils;
  21. IMPORT StrEdit;
  22. IMPORT StringIO;
  23. IMPORT SYSTEM;
  24. VAR
  25. Initialized : BOOLEAN;
  26. CONST
  27. blank = ' ';
  28. VAR
  29. ten, zero, one : NumTypes.Real8;
  30. PROCEDURE StrToReal(TheStr : ARRAY OF CHAR; StartingSpot :
  31. CARDINAL; VAR TheReal : NumTypes.Real8): BOOLEAN;
  32. CONST
  33. ten = 10.0;
  34. one = 1.0;
  35. zero = 0.0;
  36. digitsize = 16;
  37. OrdZero = 48;
  38. VAR
  39. digit : ARRAY [1..digitsize] OF INTEGER;
  40. expstr : ARRAY [0..24] OF CHAR;
  41. temp, WholeNum, r, fac : NumTypes.Real8;
  42. scalesign, negative : BOOLEAN;
  43. scale, DigitsRightOfDec, exp : INTEGER;
  44. NumOfBlanks, Zeroes, DecPt, EPos : INTEGER;
  45. lngth, limit, spot, DigitArrayIndex, j : INTEGER;
  46. BEGIN
  47. TheReal := 0.0;
  48. exp := 0;
  49. DigitsRightOfDec := 0;
  50. lngth := M2Strings.Length(TheStr);
  51. spot := StartingSpot;
  52. negative := FALSE;
  53. WHILE (spot<lngth) AND (TheStr[spot]#'.') AND
  54. ((TheStr[spot]<'0') OR (TheStr[spot]>'9')) DO
  55. IF TheStr[spot]='-' THEN
  56. negative := NOT negative;
  57. ELSIF TheStr[spot]='+' THEN
  58. negative := FALSE;
  59. END;
  60. INC(spot);
  61. END;
  62. IF (spot>=lngth) THEN
  63. RETURN FALSE;
  64. END;
  65. DigitArrayIndex := 1;
  66. WHILE (spot<lngth) AND (DigitArrayIndex<=digitsize) AND
  67. (('0'<=TheStr[spot]) AND (TheStr[spot]<='9')) DO
  68. digit[DigitArrayIndex] := INTEGER(ORD(TheStr[spot])-OrdZero);
  69. INC(DigitArrayIndex);
  70. INC(spot);
  71. END;
  72. WholeNum := zero;
  73. FOR j := 1 TO DigitArrayIndex-1 DO
  74. WholeNum := WholeNum*ten + Numbers.IntToR8(digit[j]);
  75. END;
  76. IF negative THEN
  77. TheReal := -WholeNum;
  78. ELSE
  79. TheReal := WholeNum;
  80. END;
  81. IF (spot=lngth) OR ((TheStr[spot]#'.') AND (TheStr[spot]#'E')) THEN
  82. (*We're either at the end of the string or at the end of
  83. the part of it that contains a valid real number, and
  84. we've found at least one numeric character, so we
  85. return true. *)
  86. RETURN TRUE;
  87. END;
  88. IF (TheStr[spot]='.') THEN
  89. scale := 0;
  90. WholeNum := zero;
  91. INC(spot);
  92. WHILE (spot<lngth)
  93. AND (DigitArrayIndex<=digitsize)
  94. AND PosUtils.IsNumericChar(TheStr[spot]) DO
  95. temp := Numbers.IntToR8(ORD(TheStr[spot])-OrdZero);
  96. (* Every time we find a new digit right of the
  97. decimal point, we essentially slide the number
  98. thus far to the left one digit by multiplying
  99. it by ten, and then we add this new digit as if
  100. it were going to be the least significant digit
  101. in the final number. WholeNum is the temporary
  102. representation of the fractional part of the
  103. real number. *)
  104. IF negative THEN
  105. WholeNum := (WholeNum * ten) - temp;
  106. ELSE
  107. WholeNum := (WholeNum * ten) + temp;
  108. END;
  109. INC(scale);
  110. INC(DigitArrayIndex);
  111. INC(DigitsRightOfDec);
  112. INC(spot);
  113. END;
  114. IF WholeNum # zero THEN
  115. r := WholeNum;
  116. (* We kept track in the variable scale of how many times
  117. we multiplied the fractional part by ten to make it
  118. a whole number. Now we divide by ten that number of
  119. times to get it back down to what it really is. *)
  120. REPEAT
  121. r := r/ten;
  122. DEC(scale);
  123. UNTIL scale=0;
  124. (* Now add the fractional part to the whole number part. *)
  125. TheReal := TheReal + r;
  126. ELSE
  127. scale := 0;
  128. END;
  129. (* Now we have to worry about the possibility that the number
  130. is in scientific notation. Note that spot starts out
  131. sitting on the first non-numeric character after the
  132. fractional part of the number. *)
  133. WHILE (spot<lngth)
  134. AND PosUtils.IsWhiteSpace(TheStr[spot]) DO
  135. INC(spot);
  136. END;
  137. END;
  138. IF (spot = lngth) THEN
  139. RETURN TRUE;
  140. END;
  141. IF (TheStr[spot] # 'E') THEN
  142. RETURN TRUE;
  143. END;
  144. INC(spot);
  145. M2Strings.Copy( TheStr, spot, lngth - spot, expstr );
  146. IF NOT StrToInteger(expstr, 0, exp) THEN
  147. RETURN FALSE;
  148. END;
  149. scale := DigitsRightOfDec + exp;
  150. IF scale#0 THEN
  151. scalesign := scale<0;
  152. scale := ABS(scale);
  153. IF scale>307 THEN
  154. RETURN FALSE;
  155. END;
  156. IF TheReal # zero THEN
  157. FOR spot := 0 TO 8 DO
  158. IF CARDINAL(spot) IN BITSET(scale) THEN
  159. IF scalesign THEN
  160. TheReal := TheReal / NumTypes.R8TenPowers[spot];
  161. ELSE
  162. TheReal := TheReal * NumTypes.R8TenPowers[spot];
  163. END;
  164. END;
  165. END;
  166. END;
  167. END;
  168. RETURN TRUE;
  169. END StrToReal;
  170. PROCEDURE AppendDecoded(VAR TheStr : ARRAY OF CHAR; TheCodeChar : CHAR;
  171. StrConst : ARRAY OF CHAR);
  172. VAR
  173. CharNum, spot1, spot2 : CARDINAL;
  174. TmpStr : ARRAY [0..255] OF CHAR;
  175. tmpchar : CHAR;
  176. BEGIN
  177. spot2 := M2Strings.Pos(TheCodeChar,StrConst);
  178. spot1 := 0;
  179. WHILE spot2<=HIGH(StrConst) DO
  180. IF spot2>spot1 THEN
  181. M2Strings.Copy(StrConst, spot1, spot2-spot1, TmpStr);
  182. StrEdit.Append(TheStr, TmpStr);
  183. (* Copies everything from the start of StrConst, or from
  184. the end of the last CharCode, into TheStr. *)
  185. END;
  186. IF NOT StrToCardinal(StrConst,spot2+1,CharNum) THEN
  187. ErrorManager.WARN('Invalid string in AppendDecoded');
  188. END;
  189. tmpchar := CHR(CharNum);
  190. StrEdit.Append(TheStr, tmpchar);
  191. spot1 := spot2+4;
  192. spot2 := PosUtils.Positn(TheCodeChar,StrConst,spot2+1);
  193. END;
  194. IF spot1< M2Strings.Length(StrConst) THEN
  195. M2Strings.Copy(StrConst, spot1, M2Strings.Length(StrConst)-spot1, TmpStr);
  196. StrEdit.Append(TheStr, TmpStr);
  197. END;
  198. END AppendDecoded;
  199. PROCEDURE CardinalToStr(TheNum : CARDINAL; width : CARDINAL; VAR
  200. TheStr : ARRAY OF CHAR);
  201. VAR
  202. spot : INTEGER;
  203. tmp : ARRAY [0..80] OF CHAR;
  204. BEGIN
  205. LowLevel.Fill(SYSTEM.ADR(TheStr), 1+HIGH(TheStr), blank);
  206. (*Fill TheStr with spaces.*)
  207. spot := HIGH(TheStr);
  208. REPEAT
  209. TheStr[spot] := CHR((TheNum MOD 10)+48);
  210. TheNum := TheNum DIV 10;
  211. DEC(spot);
  212. UNTIL (TheNum<10) OR (spot<=0);
  213. IF TheNum#0 THEN
  214. TheStr[spot] := CHR(TheNum+48);
  215. END;
  216. IF M2Strings.Length(TheStr)>width THEN
  217. StrEdit.CutLeadingChars(' ', TheStr);
  218. END;
  219. IF M2Strings.Length(TheStr)<width THEN
  220. LowLevel.Fill(SYSTEM.ADR(tmp), 1+HIGH(tmp), blank);
  221. StrEdit.SetLength(tmp, width-M2Strings.Length(TheStr));
  222. StrEdit.Append(tmp, TheStr);
  223. M2Strings.Assign(tmp, TheStr);
  224. END;
  225. END CardinalToStr;
  226. PROCEDURE IntegerToStr(TheNum : INTEGER; width : CARDINAL; VAR
  227. TheStr : ARRAY OF CHAR);
  228. VAR
  229. spot : CARDINAL;
  230. BEGIN
  231. CardinalToStr(ABS(TheNum), width, TheStr);
  232. IF TheNum<0 THEN
  233. spot := LowLevel.ScanNE( M2Strings.Length(TheStr), blank,
  234. SYSTEM.ADR(TheStr) );
  235. (* find the first nonblank *)
  236. IF spot>0 THEN
  237. (* We do this to preserve the correct width,
  238. if possible. *)
  239. TheStr[spot-1] := '-';
  240. ELSE
  241. M2Strings.Insert('-', TheStr, spot);
  242. END;
  243. END;
  244. END IntegerToStr;
  245. TYPE
  246. LongAndShort =
  247. RECORD
  248. CASE : CHAR OF
  249. 'A' :
  250. longi : LONGINT;
  251. | 'B' :
  252. locard, hicard : CARDINAL;
  253. | 'C' :
  254. loint, hiint : INTEGER;
  255. END;
  256. END;
  257. VAR
  258. TenPowers : ARRAY [0..9] OF LongAndShort;
  259. PROCEDURE LongIntegerToStr(TheNum : LONGINT; width : CARDINAL;
  260. VAR TheStr : ARRAY OF CHAR);
  261. VAR
  262. LongConv : LongAndShort;
  263. positive : BOOLEAN;
  264. charstr : ARRAY [0..80] OF CHAR;
  265. i : CARDINAL;
  266. tmpchar: CHAR;
  267. BEGIN
  268. LongConv.longi := TheNum;
  269. IF LongConv.hiint < 0 THEN
  270. TheNum := -TheNum;
  271. positive := FALSE;
  272. ELSE
  273. positive := TRUE;
  274. END;
  275. (* Fill(ADR(charstr), 10, '0'); replaced below *)
  276. charstr[10] := 0C;
  277. FOR i := 0 TO 9 DO
  278. tmpchar := '0';
  279. WHILE NOT (TheNum < TenPowers[i].longi) DO
  280. INC( tmpchar);
  281. TheNum := TheNum - TenPowers[i].longi;
  282. END;
  283. charstr[i] := tmpchar;
  284. END;
  285. StrEdit.CutLeadingChars('0', charstr);
  286. IF NOT positive THEN
  287. M2Strings.Insert('-', charstr, 0);
  288. END;
  289. IF charstr[0]=0C THEN
  290. charstr[0] := '0';
  291. charstr[1] := 0C;
  292. END;
  293. M2Strings.Assign(charstr, TheStr);
  294. IF M2Strings.Length(TheStr)<width THEN
  295. LowLevel.Fill(SYSTEM.ADR(charstr), 1+HIGH(charstr), blank);
  296. StrEdit.SetLength(charstr, width-M2Strings.Length(TheStr));
  297. StrEdit.Append(charstr, TheStr);
  298. M2Strings.Assign(charstr, TheStr);
  299. END;
  300. END LongIntegerToStr;
  301. (*$O-*)
  302. (*We turn off optimization for this procedure because of a bug in
  303. the beta copy of Logitech's v3.0.*)
  304. PROCEDURE StrToLongInteger(TheStr : ARRAY OF CHAR; StartingSpot :
  305. CARDINAL; VAR TheLong : LONGINT) : BOOLEAN;
  306. VAR
  307. positive : BOOLEAN;
  308. ten : LONGINT;
  309. dumlong : LongAndShort;
  310. charstr : ARRAY [0..10] OF CHAR;
  311. leng : CARDINAL;
  312. BEGIN
  313. leng := M2Strings.Length(TheStr);
  314. TheLong := NumTypes.L0;
  315. ten := Numbers.Lc(10);
  316. positive := TRUE;
  317. WHILE (StartingSpot<leng) AND ((TheStr[StartingSpot]<'0')
  318. OR (TheStr[StartingSpot]>'9')) DO
  319. IF TheStr[StartingSpot]='-' THEN
  320. positive := FALSE;
  321. END;
  322. INC(StartingSpot);
  323. END;
  324. IF (StartingSpot>=leng) THEN
  325. RETURN FALSE;
  326. END;
  327. WHILE (StartingSpot<leng) AND ((TheStr[StartingSpot]>='0'
  328. ) AND (TheStr[StartingSpot]<='9')) DO
  329. TheLong := TheLong * ten;
  330. dumlong.hicard := 0;
  331. dumlong.locard := ORD(TheStr[StartingSpot])-48;
  332. TheLong := TheLong + dumlong.longi;
  333. INC(StartingSpot);
  334. END;
  335. IF NOT positive THEN
  336. TheLong := -TheLong;
  337. END;
  338. RETURN TRUE;
  339. END StrToLongInteger;
  340. (*$O=*)
  341. PROCEDURE StrToCardinal(TheStr : ARRAY OF CHAR; StartingSpot :
  342. CARDINAL; VAR TheCard : CARDINAL) : BOOLEAN;
  343. VAR
  344. spot, StrLen : CARDINAL;
  345. BEGIN
  346. spot := StartingSpot;
  347. TheCard := 0;
  348. StrLen := M2Strings.Length(TheStr);
  349. WHILE ((spot<StrLen) AND ((TheStr[spot]<'0'
  350. ) OR (TheStr[spot]>'9'))) DO
  351. INC(spot);
  352. (*Skips all leading non-numeric stuff.*)
  353. END;
  354. IF spot>=StrLen THEN
  355. RETURN FALSE;
  356. END;
  357. WHILE (spot<StrLen) AND (TheStr[spot]>='0'
  358. ) AND (TheStr[spot]<='9') DO
  359. TheCard := TheCard*10;
  360. INC(TheCard, ORD(TheStr[spot])-48);
  361. INC(spot);
  362. END;
  363. RETURN TRUE;
  364. END StrToCardinal;
  365. PROCEDURE StrToInteger(TheStr : ARRAY OF CHAR; StartingSpot :
  366. CARDINAL; VAR TheInt : INTEGER) : BOOLEAN;
  367. VAR
  368. spot, StrLen : CARDINAL;
  369. negative : BOOLEAN;
  370. BEGIN
  371. spot := StartingSpot;
  372. TheInt := 0;
  373. StrLen := M2Strings.Length(TheStr);
  374. negative := FALSE;
  375. WHILE ((spot<StrLen) AND ((TheStr[spot]<'0'
  376. ) OR (TheStr[spot]>'9'))) DO
  377. IF TheStr[spot]='-' THEN
  378. negative := NOT negative;
  379. (* Means negative will go back to FALSE if
  380. there are two leading minus signs; may
  381. not be good for much, but why not? *)
  382. END;
  383. INC(spot);
  384. (*Skips all leading non-numeric stuff.*)
  385. END;
  386. IF spot>=StrLen THEN
  387. RETURN FALSE;
  388. END;
  389. WHILE (spot<StrLen) AND (TheStr[spot]>='0'
  390. ) AND (TheStr[spot]<='9') DO
  391. TheInt := TheInt*10;
  392. INC(TheInt, ORD(TheStr[spot])-48);
  393. INC(spot);
  394. END;
  395. IF negative THEN
  396. TheInt := -TheInt;
  397. END;
  398. RETURN TRUE;
  399. END StrToInteger;
  400. PROCEDURE DateToStr(month, day, year : CARDINAL; VAR TheStr :
  401. ARRAY OF CHAR);
  402. VAR
  403. DayStr, MnthStr, YrStr : ARRAY [0..15] OF CHAR;
  404. BEGIN
  405. CardinalToStr(day, 2, DayStr);
  406. IF DayStr[0]=' ' THEN
  407. DayStr[0] := '0';
  408. END;
  409. CardinalToStr(month, 2, MnthStr);
  410. CardinalToStr(year, 2, YrStr);
  411. IF M2Strings.Length(YrStr)=4 THEN
  412. (*Delete the '19' if it is present.*)
  413. M2Strings.Delete(YrStr, 0, 2);
  414. END;
  415. M2Strings.Assign(MnthStr, TheStr);
  416. StrEdit.Append(TheStr, '-');
  417. StrEdit.Append(TheStr, DayStr);
  418. StrEdit.Append(TheStr, '-');
  419. StrEdit.Append(TheStr, YrStr);
  420. END DateToStr;
  421. PROCEDURE TimeToStr(hours, minutes, seconds, hundredths : CARDINAL;
  422. VAR TheStr : ARRAY OF CHAR);
  423. VAR
  424. HundrStr, SecStr, MinStr, HourStr : ARRAY [0..20] OF CHAR;
  425. pm : BOOLEAN;
  426. BEGIN
  427. CardinalToStr(hundredths, 2, HundrStr);
  428. IF HundrStr[0]=' ' THEN
  429. HundrStr[0] := '0';
  430. END;
  431. CardinalToStr(seconds, 2, SecStr);
  432. IF SecStr[0]=' ' THEN
  433. SecStr[0] := '0';
  434. END;
  435. CardinalToStr(minutes, 2, MinStr);
  436. IF MinStr[0]=' ' THEN
  437. MinStr[0] := '0';
  438. END;
  439. pm := hours>=12;
  440. (* 10 July 87: changed from hours > 12 at suggestion of
  441. H. A. Hofmans to correct problem with the first noon
  442. hour being called am. *)
  443. IF hours>12 THEN
  444. DEC(hours, 12);
  445. END;
  446. CardinalToStr(hours, 2, HourStr);
  447. M2Strings.Assign(HourStr, TheStr);
  448. StrEdit.Append(TheStr, ':');
  449. StrEdit.Append(TheStr, MinStr);
  450. StrEdit.Append(TheStr, ':');
  451. StrEdit.Append(TheStr, SecStr);
  452. StrEdit.Append(TheStr, ':');
  453. StrEdit.Append(TheStr, HundrStr);
  454. IF pm THEN
  455. StrEdit.Append(TheStr, 'p');
  456. ELSE
  457. StrEdit.Append(TheStr, 'a');
  458. END;
  459. END TimeToStr;
  460. PROCEDURE RealToStr( TheNum: NumTypes.Real8; DigitsRightOfDec,
  461. width: INTEGER; VAR TheStr: ARRAY OF CHAR);
  462. CONST
  463. ten = 10.0;
  464. one = 1.0;
  465. zero = 0.0;
  466. VAR
  467. spot : CARDINAL;
  468. i, exp : INTEGER;
  469. expstr : ARRAY [0..6] OF CHAR;
  470. tmpstr : ARRAY [0..31] OF CHAR;
  471. PROCEDURE PutDigit(VAR r : NumTypes.Real8);
  472. VAR
  473. dig : LONGINT;
  474. d : CARDINAL;
  475. WholePart : NumTypes.Real8;
  476. BEGIN
  477. dig := Numbers.R8ToL(r);
  478. d := Numbers.C(dig);
  479. tmpstr[spot] := CHR(d+ORD('0'));
  480. INC(spot);
  481. WholePart := Numbers.LToR8(dig);
  482. r := r - WholePart;
  483. END PutDigit;
  484. BEGIN
  485. LowLevel.Fill(SYSTEM.ADR(tmpstr), 1+HIGH(tmpstr), 0C);
  486. (*Fill tmpstr with nulls.*)
  487. spot := 0;
  488. IF TheNum<zero THEN
  489. tmpstr[spot] := '-';
  490. INC(spot);
  491. TheNum := -TheNum;
  492. END;
  493. exp := 0;
  494. IF TheNum#zero THEN
  495. LOOP
  496. IF TheNum<one THEN
  497. TheNum := TheNum*ten;
  498. DEC(exp);
  499. ELSIF TheNum>=ten THEN
  500. TheNum := TheNum/ten;
  501. INC(exp);
  502. ELSE
  503. EXIT;
  504. END;
  505. END;
  506. END;
  507. PutDigit(TheNum);
  508. tmpstr[spot] := '.';
  509. INC(spot);
  510. FOR i := 1 TO 15 DO
  511. TheNum := TheNum*ten;
  512. PutDigit(TheNum);
  513. END;
  514. tmpstr[spot] := 'E';
  515. IntegerToStr(exp, 0, expstr);
  516. StrEdit.Append(tmpstr, expstr);
  517. IF DigitsRightOfDec < 0 THEN
  518. RETURN;
  519. END;
  520. IF NOT ScientificToPlain( tmpstr, DigitsRightOfDec,
  521. width, TheStr ) THEN
  522. ErrorManager.WARN('Invalid real');
  523. END;
  524. END RealToStr;
  525. PROCEDURE ReturnedCard( TheStr: ARRAY OF CHAR ):
  526. CARDINAL;
  527. VAR
  528. tmpc: CARDINAL;
  529. BEGIN
  530. IF NOT StrToCardinal( TheStr, 0, tmpc ) THEN
  531. StrEdit.Append( TheStr, ' # number' );
  532. ErrorManager.WARN( TheStr );
  533. END;
  534. RETURN tmpc;
  535. END ReturnedCard;
  536. PROCEDURE ReturnedInt( TheStr: ARRAY OF CHAR ):
  537. INTEGER;
  538. VAR
  539. tmpi: INTEGER;
  540. BEGIN
  541. IF NOT StrToInteger( TheStr, 0, tmpi ) THEN
  542. StrEdit.Append( TheStr, ' # number' );
  543. ErrorManager.WARN( TheStr );
  544. END;
  545. RETURN tmpi;
  546. END ReturnedInt;
  547. PROCEDURE ScientificToPlain(scientific : ARRAY OF CHAR;
  548. DigitsToRight, width : CARDINAL; VAR plain : ARRAY OF CHAR) :
  549. BOOLEAN;
  550. VAR
  551. RoundSpot, lngth, FirstSpot, eSpot, DotSpot,
  552. ProperNumOfDigits : CARDINAL;
  553. cnt, DecimalShift : INTEGER;
  554. tmpstr : ARRAY [0..79] OF CHAR;
  555. carrying : BOOLEAN;
  556. e, dot, space, zero : ARRAY [0..0] OF CHAR;
  557. (* We use these instead of CHAR constants because this
  558. procedure was actually written for the ITC version.
  559. See CharStuf module chapter for explanation. *)
  560. BEGIN
  561. e[0] := 'E';
  562. dot[0] := '.';
  563. space[0] := ' ';
  564. zero[0] := '0';
  565. eSpot := M2Strings.Pos(e,scientific);
  566. IF NOT StrToInteger(scientific, eSpot, DecimalShift) THEN
  567. RETURN FALSE;
  568. END;
  569. M2Strings.Assign(scientific, tmpstr);
  570. M2Strings.Delete(tmpstr, eSpot,
  571. (M2Strings.Length(tmpstr) - eSpot) + 1);
  572. DotSpot := M2Strings.Pos(dot,tmpstr);
  573. IF DotSpot>HIGH(tmpstr) THEN
  574. RETURN FALSE;
  575. ELSE
  576. M2Strings.Delete(tmpstr, DotSpot, 1);
  577. END;
  578. IF tmpstr[0]='-' THEN
  579. FirstSpot := 1;
  580. ELSE
  581. FirstSpot := 0;
  582. END;
  583. IF DecimalShift>=0 THEN
  584. DotSpot := DotSpot + CARDINAL(DecimalShift);
  585. ELSE
  586. DecimalShift := -DecimalShift;
  587. FOR cnt := 1 TO DecimalShift DO
  588. M2Strings.Insert(zero, tmpstr, FirstSpot);
  589. END;
  590. DotSpot := FirstSpot + 1;
  591. END;
  592. ProperNumOfDigits := (DotSpot + DigitsToRight);
  593. lngth := M2Strings.Length(tmpstr) + 1;
  594. IF lngth > ProperNumOfDigits THEN
  595. IF LowLevel.ScanNE( ProperNumOfDigits, '9', SYSTEM.ADR(tmpstr)
  596. ) < INTEGER(ProperNumOfDigits) THEN
  597. (*We can round up without extending length of string.*)
  598. RoundSpot := ProperNumOfDigits;
  599. carrying := FALSE;
  600. WHILE RoundSpot > 0 DO
  601. IF (tmpstr[RoundSpot] >= '5') OR carrying THEN
  602. INC( tmpstr[RoundSpot - 1] );
  603. carrying := FALSE;
  604. END;
  605. DEC(RoundSpot);
  606. IF tmpstr[RoundSpot] = ':' THEN
  607. (*We tried to round up a 9.*)
  608. carrying := TRUE;
  609. tmpstr[RoundSpot] := '0';
  610. ELSIF tmpstr[RoundSpot] = '/' THEN
  611. carrying := TRUE;
  612. (*We meant to round up the first digit to the
  613. left of the decimal point, but actually rounded up
  614. the decimal point itself. The carrying flag
  615. will correct it next time through.*)
  616. tmpstr[RoundSpot] := '.';
  617. ELSE
  618. RoundSpot := 0;
  619. (*Forces us out of the loop.*)
  620. END;
  621. END;
  622. END;
  623. M2Strings.Delete(tmpstr, ProperNumOfDigits, lngth-ProperNumOfDigits);
  624. lngth := ProperNumOfDigits + 1;
  625. ELSE
  626. WHILE (ProperNumOfDigits + 1) > lngth DO
  627. StrEdit.Append(tmpstr, zero);
  628. INC(lngth);
  629. END;
  630. END;
  631. M2Strings.Insert(dot, tmpstr, DotSpot);
  632. (*We postpone insertion of the dot so that we can scan
  633. for non-9's above.*)
  634. WHILE (lngth<width) AND (lngth < (HIGH(tmpstr)+1)) DO
  635. M2Strings.Insert(space, tmpstr, 0);
  636. INC(lngth);
  637. END;
  638. M2Strings.Assign(tmpstr, plain);
  639. RETURN TRUE;
  640. END ScientificToPlain;
  641. PROCEDURE OldSetFormToNew( OldFormStr: ARRAY OF CHAR; VAR
  642. NewFormStr: ARRAY OF CHAR );
  643. (* This procedure will be deleted in the next release. *)
  644. VAR
  645. tmpcard, last, cnt: CARDINAL;
  646. tmpstr, tmpstr2: ARRAY [0..79] OF CHAR;
  647. PROCEDURE GetSymbol( VAR TheSymbol: ARRAY OF CHAR );
  648. VAR
  649. s: ARRAY [0..0] OF CHAR;
  650. InQuote : BOOLEAN;
  651. WhichQuote : CHAR;
  652. BEGIN
  653. TheSymbol[0] := 0C;
  654. IF OldFormStr[cnt] = '.' THEN
  655. StrEdit.Append( TheSymbol, '..' );
  656. INC( cnt );
  657. RETURN;
  658. END;
  659. s[0] := OldFormStr[cnt];
  660. InQuote := FALSE;
  661. WhichQuote := 0C;
  662. REPEAT
  663. IF InQuote OR (NOT PosUtils.Present(s, ';.')) THEN
  664. StrEdit.Append( TheSymbol, s );
  665. END;
  666. IF (s[0] = '"') OR (s[0] = "'") THEN
  667. IF InQuote THEN
  668. IF (WhichQuote = s[0]) THEN
  669. InQuote := FALSE;
  670. END;
  671. ELSE
  672. InQuote := TRUE;
  673. WhichQuote := s[0];
  674. END
  675. END;
  676. INC( cnt );
  677. IF cnt <= last THEN
  678. s[0] := OldFormStr[cnt];
  679. END;
  680. UNTIL (cnt > last) OR ( (NOT InQuote) AND PosUtils.Present(s,
  681. ';.') );
  682. INC( cnt );
  683. StrEdit.CrunchBlanks( TheSymbol );
  684. END GetSymbol;
  685. BEGIN
  686. last := M2Strings.Length( OldFormStr );
  687. IF last > 0 THEN
  688. DEC( last );
  689. ELSE
  690. StrEdit.AssignStr( "{0..400}", NewFormStr );
  691. RETURN;
  692. END;
  693. StrEdit.AssignStr( "{", NewFormStr );
  694. cnt := 0;
  695. REPEAT
  696. GetSymbol( tmpstr );
  697. IF CAP(tmpstr[0]) = 'E' THEN
  698. IF NOT StrToCardinal( tmpstr, 1, tmpcard ) THEN
  699. ErrorManager.WARN('Bad set string.');
  700. END;
  701. INC( tmpcard, Key.Extended );
  702. CardinalToStr( tmpcard, 0, tmpstr2 );
  703. StrEdit.Append( NewFormStr, tmpstr2 );
  704. ELSE
  705. (*These should always be numbers or ellipses.*)
  706. IF (tmpstr[0] = '.') THEN
  707. M2Strings.Delete( NewFormStr,
  708. M2Strings.Length(NewFormStr) - 1, 1 );
  709. (*delete the comma appended in the last loop*)
  710. END;
  711. StrEdit.Append( NewFormStr, tmpstr );
  712. END;
  713. IF (cnt <= last) AND (tmpstr[0] # '.') THEN
  714. StrEdit.Append( NewFormStr, ',' );
  715. END;
  716. UNTIL cnt > last;
  717. StrEdit.Append( NewFormStr, "}" );
  718. END OldSetFormToNew;
  719. PROCEDURE Init();
  720. VAR
  721. i : CARDINAL;
  722. BEGIN
  723. IF Initialized THEN
  724. RETURN;
  725. ELSE
  726. Initialized := TRUE;
  727. END;
  728. ErrorManager.Init();
  729. Key.Init();
  730. LowLevel.Init();
  731. M2Strings.Init();
  732. Numbers.Init();
  733. NumTypes.Init();
  734. PosUtils.Init();
  735. StrEdit.Init();
  736. (*EntryDiag:
  737. StringIO.WriteEol( 1, 'Entering StrConv' );
  738. :EntryDiag*)
  739. FOR i := 5 TO 9 DO
  740. TenPowers[i].hicard := 0;
  741. END;
  742. TenPowers[9].locard := 1;
  743. TenPowers[8].locard := 10;
  744. TenPowers[7].locard := 100;
  745. TenPowers[6].locard := 1000;
  746. TenPowers[5].locard := 10000;
  747. TenPowers[4].locard := 34464; (* 100,000 *)
  748. TenPowers[3].locard := 16960; (* 1,000,000 *)
  749. TenPowers[2].locard := 38528; (* 10,000,000 *)
  750. TenPowers[1].locard := 57600; (* 100,000,000 *)
  751. TenPowers[0].locard := 51712; (* 1,000,000,000 *)
  752. TenPowers[4].hicard := 1; (* 100,000 *)
  753. TenPowers[3].hicard := 15; (* 1,000,000 *)
  754. TenPowers[2].hicard := 152; (* 10,000,000 *)
  755. TenPowers[1].hicard := 1525; (* 100,000,000 *)
  756. TenPowers[0].hicard := 15258; (* 1,000,000,000 *)
  757. (*EntryDiag:
  758. StringIO.WriteEol( 1, 'Exiting StrConv' );
  759. :EntryDiag*)
  760. END Init;
  761. BEGIN
  762. Initialized := FALSE;
  763. Init();
  764. END StrConv.