PRINTFBA.MOD 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * PRINTFBA.MOD - COMMS Toolkit formatted i/o support *
  5. * *
  6. * COPYRIGHT (C) 1988..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. IMPLEMENTATION MODULE PrintFBase;
  11. IMPORT Lib,IO;
  12. CONST
  13. MaxArgs = 5;
  14. UpperDigits = '0123456789ABCDEF';
  15. LowerDigits = '0123456789abcdef';
  16. TYPE
  17. StringPtr = POINTER TO ARRAY[0..0FFFH] OF CHAR;
  18. JustifyTypes = (Left,Right,Centre);
  19. CardType = (short,card,long);
  20. CardPointer = POINTER TO RECORD
  21. CASE :CardType OF
  22. short : shortp : SHORTCARD; |
  23. card : cardp : CARDINAL; |
  24. long : longp : LONGCARD; |
  25. END;
  26. END;
  27. VAR
  28. PatAddr,DestAddr : StringPtr;
  29. NumberBase : LONGCARD;
  30. ArgNo,ArgCount,Patp,
  31. Destp,PatMax,DestMax: CARDINAL;
  32. ArgList : ARRAY[0..MaxArgs-1] OF ADDRESS;
  33. Size : ARRAY[0..MaxArgs-1] OF CARDINAL;
  34. Digits : ARRAY[0..15] OF CHAR;
  35. Convert : ARRAY[0..51] OF PROC;
  36. (*....................................*)
  37. PROCEDURE Length(VAR s:ARRAY OF CHAR; Max:CARDINAL):CARDINAL;
  38. BEGIN
  39. RETURN Lib.ScanR(ADR(s),Max,0C);
  40. END Length;
  41. (*....................................*)
  42. PROCEDURE Justify(Justification:JustifyTypes;VAR dest:ARRAY OF CHAR;Lnth:CARDINAL;PadChar:CHAR):CARDINAL;
  43. VAR
  44. Len : CARDINAL;
  45. BEGIN
  46. Len := Lib.ScanR(ADR(dest),HIGH(dest)+1,0C);
  47. LOOP
  48. IF Len>=Lnth THEN
  49. EXIT;
  50. END;
  51. IF (Justification=Right) OR (Justification=Centre) THEN
  52. INC(Len);
  53. Lib.Move(ADR(dest),ADR(dest[1]),Len);
  54. dest[0]:=PadChar;
  55. END;
  56. IF Len>=Lnth THEN
  57. EXIT;
  58. END;
  59. IF (Justification=Left) OR (Justification=Centre) THEN
  60. dest[Len]:=PadChar;
  61. INC(Len);
  62. dest[Len]:=0C;
  63. END
  64. END;
  65. RETURN Len;
  66. END Justify;
  67. (*............................................*)
  68. PROCEDURE Error(ErrNo:CARDINAL);
  69. VAR
  70. argnumstr : ARRAY[0..9] OF CHAR;
  71. BEGIN
  72. IO.WrLn;
  73. IO.WrStr('PrintF Error --> ');
  74. CASE ErrNo OF
  75. 1 : IO.WrStr('Unexpected end of spec. input.'); |
  76. 2 : IO.WrStr('Argument does not match specification.');|
  77. 3 : IO.WrStr('Wrong number of args.'); |
  78. 4 : IO.WrStr('Not a recognised field specifier'); |
  79. 5 : IO.WrStr('Not enough room in dest string.'); |
  80. 6 : IO.WrStr('Char codes must be three digits.'); |
  81. 7 : IO.WrStr('Width argument must be cardinal.'); |
  82. 8 : IO.WrStr('NewConversion, Type Char must be in {a..z, A..Z}');|
  83. END; (* cases *)
  84. IO.WrLn;
  85. HALT;
  86. END Error;
  87. (*....................................*)
  88. PROCEDURE CToS(c:LONGCARD; VAR i:CARDINAL);
  89. BEGIN
  90. IF c>=NumberBase THEN
  91. CToS(c DIV NumberBase,i);
  92. END;
  93. DestString[i] := Digits[CARDINAL(c MOD NumberBase)];
  94. INC(i);
  95. END CToS;
  96. (*....................................*)
  97. PROCEDURE ReadLong(VAR l:LONGCARD);
  98. VAR
  99. p : CardPointer;
  100. BEGIN
  101. p := Data;
  102. IF DataSize=1 THEN
  103. l := LONGCARD(p^.shortp)
  104. ELSIF DataSize=2 THEN
  105. l := LONGCARD(p^.cardp)
  106. ELSIF DataSize=4 THEN
  107. l := p^.longp
  108. ELSE
  109. Error(2);
  110. END;
  111. END ReadLong;
  112. (*....................................*)
  113. PROCEDURE CardToString;
  114. (* Handle conversion to string of SHORTCARD,CARDINAL and LONGCARD for*)
  115. (* all number bases from 2-16. Note that only bases 8,10 & 16 are *)
  116. (* supported by the field spec protocol. *)
  117. VAR
  118. i : CARDINAL;
  119. c : LONGCARD;
  120. BEGIN
  121. IF TypeChar='o' THEN
  122. NumberBase := 8;
  123. ELSIF TypeChar='u' THEN
  124. NumberBase := 10;
  125. ELSE
  126. NumberBase := 16;
  127. END;
  128. ReadLong(c);
  129. i:=0;
  130. IF AlwaysSigned THEN
  131. DestString[0]:=Positive;
  132. INC(i);
  133. END;
  134. CToS(c,i);
  135. DestString[i]:=0C;
  136. END CardToString;
  137. (*....................................*)
  138. PROCEDURE LowerCaseHex;
  139. BEGIN
  140. Digits:=LowerDigits;
  141. CardToString;
  142. Digits:=UpperDigits
  143. END LowerCaseHex;
  144. (*....................................*)
  145. PROCEDURE IntToString;
  146. (* Handle conversion to string of SHORTINT,INTEGER and LONGINT *)
  147. VAR
  148. i : CARDINAL;
  149. p : CardPointer;
  150. x : LONGINT;
  151. BEGIN
  152. NumberBase := 10;
  153. p := Data;
  154. IF DataSize=1 THEN
  155. x := LONGINT(SHORTINT(p^.shortp))
  156. ELSIF DataSize=2 THEN
  157. x := LONGINT(INTEGER(p^.cardp))
  158. ELSIF DataSize=4 THEN
  159. x := LONGINT(p^.longp)
  160. ELSE
  161. Error(2);
  162. END;
  163. i:=0;
  164. IF x<0 THEN
  165. DestString[0]:='-'; INC(i); x:=-x
  166. ELSIF AlwaysSigned THEN
  167. DestString[0]:=Positive; INC(i)
  168. END;
  169. CToS(LONGCARD(x),i);
  170. DestString[i]:=0C;
  171. END IntToString;
  172. (*....................................*)
  173. PROCEDURE CopyString;
  174. VAR
  175. Lnth : CARDINAL;
  176. stringp : StringPtr;
  177. BEGIN
  178. stringp := Data;
  179. Lnth := Length(stringp^,DataSize);
  180. Lib.Move(Data,ADR(DestString),Lnth);
  181. DestString[Lnth] := 0C;
  182. END CopyString;
  183. (*....................................*)
  184. PROCEDURE StoreChar(Ch:CHAR);
  185. BEGIN
  186. IF Destp<>DestMax THEN
  187. DestAddr^[Destp] := Ch;
  188. INC(Destp);
  189. END;
  190. END StoreChar;
  191. (*....................................*)
  192. PROCEDURE CopyChar;
  193. VAR
  194. charp : POINTER TO CHAR;
  195. BEGIN
  196. IF DataSize=1 THEN
  197. charp := Data;
  198. DestString[0] := charp^;
  199. DestString[1] := 0C
  200. ELSE
  201. Error(2)
  202. END;
  203. END CopyChar;
  204. (*....................................*)
  205. PROCEDURE Parse;
  206. VAR
  207. Ch : CHAR;
  208. (*. . . . . . . . . . . . . . . . . . .*)
  209. PROCEDURE GetChar(VAR Ch:CHAR):BOOLEAN;
  210. BEGIN
  211. IF Patp=PatMax THEN
  212. Ch := 0C;
  213. ELSE
  214. Ch := PatAddr^[Patp];
  215. INC(Patp);
  216. END;
  217. RETURN Ch<>0C;
  218. END GetChar;
  219. (*. . . . . . . . . . . . . . . . . . .*)
  220. PROCEDURE NextChar;
  221. BEGIN
  222. IF NOT GetChar(Ch) THEN
  223. Error(1);
  224. END;
  225. END NextChar;
  226. (*. . . . . . . . . . . . . . . . . . .*)
  227. PROCEDURE ReadNumber(VAR c:CARDINAL);
  228. VAR
  229. temp : LONGCARD;
  230. BEGIN
  231. IF Ch='*' THEN
  232. NextChar;
  233. IF ArgNo=ArgCount THEN
  234. Error(3);
  235. END;
  236. Data:=ArgList[ArgNo];
  237. DataSize:=Size[ArgNo];
  238. INC(ArgNo);
  239. ReadLong(temp);
  240. IF temp>255 THEN
  241. Error(7);
  242. ELSE
  243. c:=CARDINAL(temp);
  244. END;
  245. ELSE
  246. c := 0;
  247. WHILE (Ch>='0') AND (Ch<='9') DO
  248. c := c*10 + ORD(Ch)-48;
  249. NextChar;
  250. END;
  251. END;
  252. END ReadNumber;
  253. (*. . . . . . . . . . . . . . . . . . .*)
  254. PROCEDURE FieldSpecification;
  255. VAR
  256. Lnth,i : CARDINAL;
  257. Just : JustifyTypes;
  258. TestCh : CHAR;
  259. BEGIN
  260. IF ArgNo=ArgCount THEN
  261. Error(3);
  262. END;
  263. RightJustify:=TRUE;
  264. FieldWidth:=0;
  265. Places:=5;
  266. PadChar:=' ';
  267. AlwaysSigned:=FALSE;
  268. NextChar;
  269. IF Ch='%' THEN
  270. StoreChar(Ch);
  271. RETURN;
  272. END;
  273. LOOP
  274. IF Ch='-' THEN
  275. RightJustify:=FALSE;
  276. NextChar;
  277. ELSIF (Ch='+') OR (Ch=' ') THEN
  278. AlwaysSigned:=TRUE; Positive:=Ch; NextChar
  279. ELSIF Ch='0' THEN
  280. PadChar:='0';
  281. NextChar;
  282. ELSIF (Ch>='1') AND (Ch<='9') THEN
  283. ReadNumber(FieldWidth);
  284. IF Ch='.' THEN
  285. NextChar;
  286. ReadNumber(Places);
  287. END;
  288. ELSE
  289. EXIT;
  290. END;
  291. END;
  292. TestCh := CAP(Ch);
  293. IF (TestCh>='A') AND (TestCh<='Z') THEN
  294. TypeChar := Ch;
  295. IF ArgNo=ArgCount THEN
  296. Error(3);
  297. END;
  298. Data := ArgList[ArgNo];
  299. DataSize := Size[ArgNo];
  300. IF (TypeChar>='a') AND (TypeChar<='z') THEN
  301. i := ORD(TypeChar)-ORD('a')
  302. ELSE
  303. i := 26 + (ORD(TypeChar)-ORD('A'))
  304. END;
  305. IF Convert[i]=NULLPROC THEN
  306. Error(4);
  307. ELSE
  308. Convert[i]();
  309. END;
  310. ELSE
  311. Error(4);
  312. END;
  313. IF RightJustify THEN
  314. Just:=Right;
  315. ELSE
  316. Just:=Left;
  317. END;
  318. Lnth := Justify(Just,DestString,FieldWidth,PadChar);
  319. IF Destp+Lnth>DestMax THEN
  320. Lnth:=DestMax-Destp;
  321. END;
  322. Lib.Move(ADR(DestString),ADR(DestAddr^[Destp]),Lnth);
  323. INC(Destp,Lnth);
  324. INC(ArgNo);
  325. END FieldSpecification;
  326. (*. . . . . . . . . . . . . . . . . . .*)
  327. PROCEDURE SwitchChar;
  328. VAR
  329. code,i : CARDINAL;
  330. c : CHAR;
  331. BEGIN
  332. NextChar;
  333. CASE CAP(Ch) OF
  334. 'B' : c:=CHR(8); |
  335. 'F' : c:=CHR(12); |
  336. 'N' : StoreChar(CHR(13));
  337. c:=CHR(10); |
  338. 'R' : c:=CHR(13); |
  339. 'T' : c:=CHR(9); |
  340. '0'..'9' : code:=ORD(Ch)-48;
  341. FOR i:=0 TO 1 DO
  342. NextChar;
  343. IF (Ch<'0') OR (Ch>'9') THEN
  344. Error(6);
  345. END;
  346. code:=code*10+ORD(Ch)-48;
  347. END;
  348. c := CHR(code); |
  349. ELSE
  350. c := Ch
  351. END; (* cases *)
  352. StoreChar(c);
  353. END SwitchChar;
  354. (*. . . . . . . . . . . . . . . . . . .*)
  355. BEGIN (* Parse *)
  356. ArgNo:=0;
  357. WHILE GetChar(Ch) DO
  358. IF Ch='%' THEN
  359. FieldSpecification
  360. ELSIF Ch='\' THEN
  361. SwitchChar
  362. ELSE
  363. StoreChar(Ch);
  364. END;
  365. END;
  366. StoreChar(0C);
  367. END Parse;
  368. (*...............................................*)
  369. PROCEDURE DoPrintF(VAR pat:ARRAY OF CHAR;VAR arg1,arg2,arg3,arg4,arg5:ARRAY OF BYTE;VAR dest:ARRAY OF CHAR;NumArgs:CARDINAL);
  370. BEGIN
  371. ArgCount := NumArgs;
  372. PatAddr:=ADR(pat);
  373. Patp:=0;
  374. PatMax:=HIGH(pat)+1;
  375. DestAddr:=ADR(dest);
  376. Destp:=0;
  377. DestMax:=HIGH(dest)+1;
  378. ArgList[0]:=ADR(arg1);
  379. Size[0]:=HIGH(arg1)+1;
  380. ArgList[1]:=ADR(arg2);
  381. Size[1]:=HIGH(arg2)+1;
  382. ArgList[2]:=ADR(arg3);
  383. Size[2]:=HIGH(arg3)+1;
  384. ArgList[3]:=ADR(arg4);
  385. Size[3]:=HIGH(arg4)+1;
  386. ArgList[4]:=ADR(arg5);
  387. Size[4]:=HIGH(arg5)+1;
  388. Digits := UpperDigits;
  389. Parse;
  390. END DoPrintF;
  391. (*...............................................*)
  392. PROCEDURE NewConversion(TypeChar:CHAR; ConvertRoutine:PROC);
  393. VAR
  394. i : CARDINAL;
  395. BEGIN
  396. IF (CAP(TypeChar)>='A') AND (CAP(TypeChar)<='Z') THEN
  397. IF (TypeChar>='a') AND (TypeChar<='z') THEN
  398. i := ORD(TypeChar)-ORD('a')
  399. ELSE
  400. i := 26 + (ORD(TypeChar)-ORD('A'))
  401. END;
  402. Convert[i] := ConvertRoutine
  403. ELSE
  404. Error(8);
  405. END;
  406. END NewConversion;
  407. (*..................................................*)
  408. PROCEDURE InitPrintF;
  409. VAR
  410. i : CARDINAL;
  411. BEGIN
  412. FOR i:=0 TO 51 DO
  413. Convert[i]:=PROC(NIL)
  414. END;
  415. NewConversion('i',IntToString);
  416. NewConversion('u',CardToString);
  417. NewConversion('H',CardToString);
  418. NewConversion('h',LowerCaseHex);
  419. NewConversion('X',CardToString);
  420. NewConversion('x',LowerCaseHex);
  421. NewConversion('o',CardToString);
  422. NewConversion('c',CopyChar);
  423. NewConversion('s',CopyString);
  424. END InitPrintF;
  425. (*..................................................*)
  426. BEGIN
  427. InitPrintF;
  428. END PrintFBase.
  429.