ENVIRONU.MOD 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. IMPLEMENTATION MODULE EnvironUtils;
  2. (*
  3. * REPERTOIRE
  4. * Release 1.6
  5. * By Charles Bradford and Cole Brecheen
  6. * (c) Copyright 1985-1991 PMI
  7. * Portland, Oregon
  8. * All rights reserved
  9. * (503) 236-1788
  10. *
  11. * $Header: D:/logfiles/mods/environu.mov 1.9 17 Mar 1991 17:52:14 coleb $
  12. *)
  13. (*EntryDiag:
  14. IMPORT Diagnostics;
  15. :EntryDiag*)
  16. IMPORT ByteFiddler;
  17. IMPORT ErrorManager;
  18. IMPORT LowLevel;
  19. IMPORT M2Strings;
  20. IMPORT FAPI;
  21. IMPORT PosUtils;
  22. IMPORT StrConv;
  23. IMPORT StrEdit;
  24. IMPORT StringIO;
  25. IMPORT SYSTEM;
  26. IMPORT VStorage;
  27. VAR
  28. Initialized : BOOLEAN;
  29. PROCEDURE Init();
  30. BEGIN
  31. IF Initialized THEN
  32. RETURN;
  33. ELSE
  34. Initialized := TRUE;
  35. END;
  36. (*EntryDiag:
  37. Diagnostics.Init();
  38. :EntryDiag*)
  39. ByteFiddler.Init();
  40. ErrorManager.Init();
  41. LowLevel.Init();
  42. M2Strings.Init();
  43. PosUtils.Init();
  44. StrConv.Init();
  45. StrEdit.Init();
  46. StringIO.Init();
  47. VStorage.Init();
  48. END Init;
  49. PROCEDURE CutFirstParam(VAR TheStr : ARRAY OF CHAR);
  50. (* use when running under Logitech's run-time debugger *)
  51. VAR
  52. spot : CARDINAL;
  53. BEGIN
  54. StrEdit.CrunchBlanks(TheStr);
  55. spot := M2Strings.Pos(' ',TheStr);
  56. IF spot<=HIGH(TheStr) THEN
  57. M2Strings.Delete(TheStr, 0, spot+1);
  58. ELSE
  59. StrEdit.SetLength(TheStr, 0);
  60. END;
  61. END CutFirstParam;
  62. PROCEDURE GetProgParams(VAR ParamStr : ARRAY OF CHAR);
  63. VAR
  64. StrAdr : LowLevel.Address8086;
  65. knownLength, errcode, cnt, tmpw, CmdLineOffs : CARDINAL;
  66. tmpc : CHAR;
  67. LastWasNull: BOOLEAN;
  68. machineMode: CARDINAL;
  69. BEGIN
  70. machineMode := 0;
  71. (* Have to initialize machineMode because DOSGETMACHINEMODE is
  72. * actually expecting the address of a single byte; we use a
  73. * CARDINAL because JPI is obstinate about letting us compare
  74. * byte values with the constants in FAPI.DEF.
  75. *)
  76. errcode := FAPI.DOSGETMACHINEMODE(SYSTEM.ADR(machineMode));
  77. IF machineMode = FAPI.MODE_REAL THEN
  78. StrAdr.seg := GetPSP();
  79. StrAdr.off := 81H;
  80. knownLength := ORD(LowLevel.PeekByte(StrAdr.seg, StrAdr.off - 1));
  81. ELSE
  82. knownLength := 0FFFFH;
  83. (* In protected mode, the command line follows the
  84. * environment block. Not so in real mode. It's in the PSP
  85. * in real mode. And in real mode, you have to pay attention
  86. * to the length byte that precedes the command line. You
  87. * can't count on null termination, which is the only thing
  88. * that signals the end of the command line in protected
  89. * mode.
  90. *)
  91. IF FAPI.DOSGETENV(
  92. SYSTEM.ADR(StrAdr.seg),
  93. SYSTEM.ADR(CmdLineOffs )) # 0 THEN
  94. ErrorManager.WARN( "Failed to get command line." );
  95. END;
  96. StrAdr.off := CmdLineOffs;
  97. tmpc := LowLevel.PeekByte(StrAdr.seg,StrAdr.off );
  98. WHILE (tmpc # 0C) DO
  99. (* Now we start on the fully qualified name of the program. *)
  100. INC(StrAdr.off);
  101. tmpc := LowLevel.PeekByte(StrAdr.seg, StrAdr.off);
  102. END;
  103. INC( StrAdr.off );
  104. END;
  105. LowLevel.Fill( SYSTEM.ADR(ParamStr), HIGH(ParamStr) + 1, 0C );
  106. (* Fill the whole thing with nulls so we don't have to worry
  107. about terminating the string in the right place. *)
  108. cnt := 0;
  109. tmpc := StrAdr.b^;
  110. (* If there are any parameters at all, this
  111. will always be a space. *)
  112. WHILE (tmpc # 0C) AND
  113. (tmpc # 377C) AND
  114. (cnt <= HIGH(ParamStr)) AND
  115. ((cnt + 1) < knownLength) DO
  116. (* Now we are on the parameters. *)
  117. INC(StrAdr.off);
  118. tmpc := StrAdr.b^;
  119. ParamStr[ cnt ] := tmpc;
  120. INC( cnt );
  121. END;
  122. END GetProgParams;
  123. PROCEDURE ParsedParam( ParamNum: CARDINAL; VAR Result: ARRAY
  124. OF CHAR ): BOOLEAN;
  125. VAR
  126. ParamCnt, BlankSpot1, BlankSpot2: CARDINAL;
  127. FullLine: ARRAY [0..255] OF CHAR;
  128. BEGIN
  129. GetProgParams( FullLine );
  130. StrEdit.CrunchBlanks( FullLine );
  131. StrEdit.Append( FullLine, ' ' );
  132. IF M2Strings.Length( FullLine ) > 1 THEN
  133. IF (ParamNum = 0) THEN
  134. ErrorManager.WARN('Zero passed to ParsedParam');
  135. END;
  136. ParamCnt := 0;
  137. BlankSpot1 := 0;
  138. BlankSpot2 := 0;
  139. WHILE (ParamCnt < ParamNum) AND
  140. (BlankSpot2 <= HIGH(FullLine) ) DO
  141. BlankSpot2 := PosUtils.Positn( ' ', FullLine, BlankSpot2 );
  142. INC( ParamCnt );
  143. IF ParamCnt < ParamNum THEN
  144. BlankSpot1 := BlankSpot2;
  145. INC( BlankSpot2 );
  146. END;
  147. END;
  148. IF BlankSpot2 > HIGH(FullLine) THEN
  149. RETURN(FALSE);
  150. ELSE
  151. IF BlankSpot1 # 0 THEN
  152. INC(BlankSpot1);
  153. END;
  154. M2Strings.Copy( FullLine, BlankSpot1,
  155. BlankSpot2 - BlankSpot1, Result );
  156. RETURN(TRUE);
  157. END;
  158. ELSE
  159. RETURN(FALSE);
  160. END;
  161. END ParsedParam;
  162. PROCEDURE GetDosVersion(VAR major, minor : CARDINAL);
  163. VAR
  164. tmpc : CARDINAL;
  165. BEGIN
  166. tmpc := 0;
  167. FAPI.DOSGETVERSION( SYSTEM.ADR(tmpc ));
  168. major := ORD( CHAR(ByteFiddler.HighByte( tmpc )) );
  169. minor := ORD( CHAR(ByteFiddler.LowByte( tmpc )) );
  170. END GetDosVersion;
  171. PROCEDURE GetPSP() : CARDINAL;
  172. VAR
  173. rgstr : LowLevel.regpack;
  174. errcode, DosVersion, Subvers, PSPseg : CARDINAL;
  175. machineMode: CARDINAL;
  176. BEGIN
  177. machineMode := 0;
  178. (* Have to initialize machineMode because DOSGETMACHINEMODE is
  179. * actually expecting the address of a single byte; we use a
  180. * CARDINAL because JPI is obstinate about letting us compare
  181. * byte values with the constants in FAPI.DEF.
  182. *)
  183. errcode := FAPI.DOSGETMACHINEMODE(SYSTEM.ADR(machineMode));
  184. IF machineMode = FAPI.MODE_REAL THEN
  185. GetDosVersion(DosVersion, Subvers);
  186. IF DosVersion >= 3 THEN
  187. rgstr.a.h := 142C; (* 62H *)
  188. ELSE
  189. rgstr.a.h := 121C; (* 51H *)
  190. END;
  191. LowLevel.msdos( rgstr);
  192. IF LowLevel.FlaggedError(rgstr.flags) THEN
  193. ErrorManager.WarnNumber("DOS error getting PSP:", ORD(rgstr.a.l));
  194. END;
  195. RETURN (rgstr.b.x);
  196. ELSE
  197. ErrorManager.WARN("Attempt to GetPSP in protected mode");
  198. END;
  199. RETURN(0);
  200. END GetPSP;
  201. PROCEDURE EnvironmentSeg(): CARDINAL;
  202. VAR
  203. pspSeg, envSeg, cmdlineOffs, errcode: CARDINAL;
  204. machineMode: CARDINAL;
  205. BEGIN
  206. machineMode := 0;
  207. (* Have to initialize machineMode because DOSGETMACHINEMODE is
  208. * actually expecting the address of a single byte; we use a
  209. * CARDINAL because JPI is obstinate about letting us compare
  210. * byte values with the constants in FAPI.DEF.
  211. *)
  212. errcode := FAPI.DOSGETMACHINEMODE(SYSTEM.ADR(machineMode));
  213. IF machineMode = FAPI.MODE_REAL THEN
  214. (* We break out the steps to make them easier to see in CodeView. *)
  215. pspSeg := GetPSP();
  216. envSeg := LowLevel.PeekWord( pspSeg, 2CH );
  217. (*Get segment address of the environment from PSP.*)
  218. ELSE
  219. errcode := FAPI.DOSGETENV(SYSTEM.ADR(envSeg), SYSTEM.ADR(cmdlineOffs));
  220. (*Even though this is FAPI, it just doesn't seem to work
  221. under DOS. That's why we're doing it differently depending
  222. on the mode we're in. cmdlineOffs is telling us where the
  223. command line is in the environment segment, but we don't care
  224. about that now.*)
  225. END;
  226. RETURN envSeg;
  227. END EnvironmentSeg;
  228. PROCEDURE ReadEnvironment(name : ARRAY OF CHAR; VAR parameter :
  229. ARRAY OF CHAR);
  230. VAR
  231. bufch : CHAR;
  232. tmpcopy : ARRAY [0..255] OF CHAR;
  233. (*expanded from [0..80] on 11 Nov 86*)
  234. found : BOOLEAN;
  235. cmdlineOffs, pspSeg, errcode, EnvSeg, EnvNdx, cnt, EqSpot: CARDINAL;
  236. machineMode: SYSTEM.BYTE;
  237. BEGIN
  238. EnvSeg := EnvironmentSeg();
  239. (* We'd like to call DOSSCANENV here, but it's not FAPI. *)
  240. EnvNdx := 0;
  241. found := FALSE;
  242. StrEdit.SetLength(parameter, 0);
  243. StrEdit.CAPstr( name );
  244. REPEAT
  245. StrEdit.SetLength(tmpcopy, 0);
  246. bufch := LowLevel.PeekByte(EnvSeg,EnvNdx);
  247. WHILE bufch # 0C DO
  248. bufch := CAP(bufch);
  249. StrEdit.Append(tmpcopy, bufch);
  250. INC(EnvNdx);
  251. bufch := LowLevel.PeekByte(EnvSeg,EnvNdx);
  252. END;
  253. IF M2Strings.Pos(name,tmpcopy)=0 THEN
  254. EqSpot := M2Strings.Pos('=',tmpcopy);
  255. IF (EqSpot<HIGH(tmpcopy)) AND
  256. (EqSpot <= (M2Strings.Length(name)+1)) THEN
  257. (* Added second condition 26 Oct 88 to prevent
  258. ReadEnvironment from returning the value for, say,
  259. M2OBJLIB when what you wanted was the value for M2OBJ. *)
  260. M2Strings.Copy(tmpcopy, EqSpot + 1,
  261. M2Strings.Length(tmpcopy) - 1 - EqSpot, parameter);
  262. found := TRUE;
  263. END;
  264. END;
  265. INC(EnvNdx);
  266. IF LowLevel.PeekByte(EnvSeg, EnvNdx) = 0C THEN
  267. found := TRUE;
  268. END;
  269. UNTIL found;
  270. WHILE M2Strings.Pos(' ',parameter)=0 DO
  271. M2Strings.Delete(parameter, 0, 1);
  272. END;
  273. END ReadEnvironment;
  274. PROCEDURE GetExeName( VAR ExeName: ARRAY OF CHAR );
  275. VAR
  276. StrAdr: LowLevel.Address8086;
  277. tmpw, count, errcode: CARDINAL;
  278. tmpc: CHAR;
  279. machineMode: CARDINAL;
  280. BEGIN
  281. machineMode := 0;
  282. ExeName[0] := 0C;
  283. StrAdr.seg := EnvironmentSeg();
  284. StrAdr.off := 0;
  285. tmpw := LowLevel.PeekWord( StrAdr.seg, StrAdr.off );
  286. (* Don't know what we're skipping over here. *)
  287. WHILE (tmpw # 0) DO
  288. INC(StrAdr.off);
  289. tmpw := LowLevel.PeekWord( StrAdr.seg, StrAdr.off );
  290. END;
  291. (* Now skip the two null bytes that terminate the set of
  292. environment strings. *)
  293. StrAdr.off := StrAdr.off + 2;
  294. (* These things just never seem to be simple. It turns out that
  295. in real mode, the exe file name doesn't exactly follow the
  296. two null bytes that terminate the set of environment strings.
  297. There are an additional couple of bytes -- a one byte value
  298. and a null byte -- following the null pair. Rather than try
  299. to figure out why, we just increment past them if we know
  300. we're in real mode. *)
  301. errcode := FAPI.DOSGETMACHINEMODE(SYSTEM.ADR(machineMode));
  302. IF machineMode = FAPI.MODE_REAL THEN
  303. StrAdr.off := StrAdr.off + 2;
  304. END;
  305. count := 0;
  306. tmpc := LowLevel.PeekByte( StrAdr.seg, StrAdr.off );
  307. ExeName[count] := tmpc;
  308. WHILE (tmpc # 0C) DO
  309. (* We are now getting the path and file name of the .EXE file. *)
  310. INC(StrAdr.off);
  311. tmpc := LowLevel.PeekByte( StrAdr.seg, StrAdr.off );
  312. INC(count);
  313. ExeName[count] := tmpc;
  314. END;
  315. END GetExeName;
  316. PROCEDURE GetDate(VAR month, day, year : CARDINAL; VAR weekday,
  317. mmddyy : ARRAY OF CHAR);
  318. VAR
  319. TimeData: FAPI.DATETIME;
  320. ErrorReturn: CARDINAL;
  321. BEGIN
  322. ErrorReturn := FAPI.DOSGETDATETIME( SYSTEM.ADR(TimeData));
  323. CASE ORD(TimeData.weekday) OF
  324. 0 :
  325. StrEdit.AssignStr('Sunday', weekday);
  326. | 1 :
  327. StrEdit.AssignStr('Monday', weekday);
  328. | 2 :
  329. StrEdit.AssignStr('Tuesday', weekday);
  330. | 3 :
  331. StrEdit.AssignStr('Wednesday', weekday);
  332. | 4 :
  333. StrEdit.AssignStr('Thursday', weekday);
  334. | 5 :
  335. StrEdit.AssignStr('Friday', weekday);
  336. | 6 :
  337. StrEdit.AssignStr('Saturday', weekday);
  338. END;
  339. month := ORD(TimeData.month);
  340. day := ORD(TimeData.day);
  341. year := ORD(TimeData.year);
  342. StrConv.DateToStr(month, day, year, mmddyy);
  343. IF ErrorReturn # 0 THEN
  344. ErrorManager.WarnNumber("DOSGETDATETIME", ErrorReturn);
  345. END;
  346. END GetDate;
  347. PROCEDURE SetDate(month, day, year : CARDINAL): BOOLEAN;
  348. VAR
  349. TimeData: FAPI.DATETIME;
  350. BEGIN
  351. IF FAPI.DOSGETDATETIME( SYSTEM.ADR(TimeData )) = 0 THEN
  352. END;
  353. TimeData.month := SYSTEM.BYTE(CHR(month));
  354. TimeData.day := SYSTEM.BYTE(CHR(day));
  355. TimeData.year := year;
  356. RETURN FAPI.DOSSETDATETIME( SYSTEM.ADR(TimeData )) = 0;
  357. END SetDate;
  358. PROCEDURE GetTime(VAR hours, minutes, seconds, hundredths : CARDINAL;
  359. VAR text : ARRAY OF CHAR);
  360. VAR
  361. TimeData: FAPI.DATETIME;
  362. ErrorReturn:CARDINAL;
  363. BEGIN
  364. ErrorReturn := FAPI.DOSGETDATETIME( SYSTEM.ADR(TimeData));
  365. hours := ORD(TimeData.hours);
  366. minutes := ORD(TimeData.minutes);
  367. seconds := ORD(TimeData.seconds);
  368. hundredths := ORD(TimeData.hundredths);
  369. StrConv.TimeToStr(hours,minutes,seconds,hundredths,text);
  370. END GetTime;
  371. PROCEDURE SetTime(hours, minutes, seconds, hundredths : CARDINAL);
  372. VAR
  373. TimeData:FAPI.DATETIME;
  374. BEGIN
  375. IF FAPI.DOSGETDATETIME( SYSTEM.ADR(TimeData )) = 0 THEN
  376. END;
  377. TimeData.hours := SYSTEM.BYTE(CHR(hours));
  378. TimeData.minutes := SYSTEM.BYTE(CHR(minutes));
  379. TimeData.seconds := SYSTEM.BYTE(CHR(seconds));
  380. TimeData.hundredths := SYSTEM.BYTE(CHR(hundredths));
  381. IF FAPI.DOSSETDATETIME( SYSTEM.ADR(TimeData )) = 0 THEN
  382. END;
  383. END SetTime;
  384. PROCEDURE MemAvail(within: CARDINAL) : CARDINAL;
  385. VAR
  386. lasttry, lowtry, try : CARDINAL;
  387. BEGIN
  388. lasttry := 65535;
  389. try := 65535;
  390. lowtry := 0;
  391. LOOP
  392. WHILE (NOT VStorage.DosAvail(try)) AND (try>16) DO
  393. lasttry := try;
  394. try := lowtry + (try-lowtry) DIV 2;
  395. END;
  396. IF ((lasttry-try) > within) AND (try>16) THEN
  397. lowtry := try;
  398. try := try + (lasttry-try) DIV 2;
  399. ELSE
  400. EXIT;
  401. END;
  402. END;
  403. IF try<=16 THEN
  404. RETURN 0;
  405. ELSE
  406. RETURN try;
  407. END;
  408. END MemAvail;
  409. BEGIN
  410. Initialized := FALSE;
  411. Init();
  412. END EnvironUtils.