readwrite.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /* R E A D ( L N ) & W R I T E ( L N ) */
  2. #include "debug.h"
  3. #include <assert.h>
  4. #include <em.h>
  5. #include "LLlex.h"
  6. #include "def.h"
  7. #include "main.h"
  8. #include "misc.h"
  9. #include "node.h"
  10. #include "scope.h"
  11. #include "type.h"
  12. /* DEBUG */
  13. #include "idf.h"
  14. extern char *sprint();
  15. ChkRead(arg)
  16. register struct node *arg;
  17. {
  18. struct node *file;
  19. char *name = "read";
  20. char *message, buff[80];
  21. extern char *ChkAllowedVar();
  22. assert(arg);
  23. assert(arg->nd_symb == ',');
  24. if( arg->nd_left->nd_type->tp_fund == T_FILE ) {
  25. file = arg->nd_left;
  26. arg = arg->nd_right;
  27. if( !arg ) {
  28. error("\"%s\": variable-access expected", name);
  29. return;
  30. }
  31. }
  32. else if( !(file = ChkStdInOut(name, 0)) )
  33. return;
  34. while( arg ) {
  35. assert(arg->nd_symb == ',');
  36. if( file->nd_type != text_type ) {
  37. /* real var & file of integer */
  38. if( !TstAssCompat(arg->nd_left->nd_type,
  39. BaseType(file->nd_type->next)) ) {
  40. node_error(arg->nd_left,
  41. "\"%s\": illegal parameter type",name);
  42. return;
  43. }
  44. else if( (BaseType(file->nd_type->next) == long_type
  45. && arg->nd_left->nd_type == int_type)
  46. ||
  47. (BaseType(file->nd_type->next) == int_type
  48. && arg->nd_left->nd_type == long_type) ) {
  49. if( int_size != long_size ) {
  50. node_error(arg->nd_left,
  51. "\"%s\": longs and integers have different sizes",name);
  52. return;
  53. }
  54. else node_warning(arg->nd_left,
  55. "\"%s\": mixture of longs and integers", name);
  56. }
  57. }
  58. else if( !(BaseType(arg->nd_left->nd_type)->tp_fund &
  59. ( T_CHAR | T_NUMERIC )) ) {
  60. node_error(arg->nd_left,
  61. "\"%s\": illegal parameter type",name);
  62. return;
  63. }
  64. message = ChkAllowedVar(arg->nd_left, 1);
  65. if( message ) {
  66. sprint(buff,"\"%%s\": %s can't be a variable parameter",
  67. message);
  68. node_error(arg->nd_left, buff, name);
  69. return;
  70. }
  71. CodeRead(file, arg->nd_left);
  72. arg = arg->nd_right;
  73. }
  74. }
  75. ChkReadln(arg)
  76. register struct node *arg;
  77. {
  78. struct node *file;
  79. char *name = "readln";
  80. char *message, buff[80];
  81. extern char *ChkAllowedVar();
  82. if( !arg ) {
  83. if( !(file = ChkStdInOut(name, 0)) )
  84. return;
  85. else {
  86. CodeReadln(file);
  87. return;
  88. }
  89. }
  90. assert(arg->nd_symb == ',');
  91. if( arg->nd_left->nd_type->tp_fund == T_FILE ) {
  92. if( arg->nd_left->nd_type != text_type ) {
  93. node_error(arg->nd_left,
  94. "\"%s\": textfile expected", name);
  95. return;
  96. }
  97. else {
  98. file = arg->nd_left;
  99. arg = arg->nd_right;
  100. }
  101. }
  102. else if( !(file = ChkStdInOut(name, 0)) )
  103. return;
  104. while( arg ) {
  105. assert(arg->nd_symb == ',');
  106. if( !(BaseType(arg->nd_left->nd_type)->tp_fund &
  107. ( T_CHAR | T_NUMERIC )) ) {
  108. node_error(arg->nd_left,
  109. "\"%s\": illegal parameter type",name);
  110. return;
  111. }
  112. message = ChkAllowedVar(arg->nd_left, 1);
  113. if( message ) {
  114. sprint(buff,"\"%%s\": %s can't be a variable parameter",
  115. message);
  116. node_error(arg->nd_left, buff, name);
  117. return;
  118. }
  119. CodeRead(file, arg->nd_left);
  120. arg = arg->nd_right;
  121. }
  122. CodeReadln(file);
  123. }
  124. ChkWrite(arg)
  125. register struct node *arg;
  126. {
  127. struct node *left, *expp, *file;
  128. char *name = "write";
  129. assert(arg);
  130. assert(arg->nd_symb == ',');
  131. assert(arg->nd_left->nd_symb == ':');
  132. left = arg->nd_left;
  133. expp = left->nd_left;
  134. if( expp->nd_type->tp_fund == T_FILE ) {
  135. if( left->nd_right ) {
  136. node_error(expp,
  137. "\"%s\": filevariable can't have a width",name);
  138. return;
  139. }
  140. file = expp;
  141. arg = arg->nd_right;
  142. if( !arg ) {
  143. error("\"%s\": expression expected", name);
  144. return;
  145. }
  146. }
  147. else if( !(file = ChkStdInOut(name, 1)) )
  148. return;
  149. while( arg ) {
  150. assert(arg->nd_symb == ',');
  151. if( !ChkWriteParameter(file->nd_type, arg->nd_left, name) )
  152. return;
  153. CodeWrite(file, arg->nd_left);
  154. arg = arg->nd_right;
  155. }
  156. }
  157. ChkWriteln(arg)
  158. register struct node *arg;
  159. {
  160. struct node *left, *expp, *file;
  161. char *name = "writeln";
  162. if( !arg ) {
  163. if( !(file = ChkStdInOut(name, 1)) )
  164. return;
  165. else {
  166. CodeWriteln(file);
  167. return;
  168. }
  169. }
  170. assert(arg->nd_symb == ',');
  171. assert(arg->nd_left->nd_symb == ':');
  172. left = arg->nd_left;
  173. expp = left->nd_left;
  174. if( expp->nd_type->tp_fund == T_FILE ) {
  175. if( expp->nd_type != text_type ) {
  176. node_error(expp, "\"%s\": textfile expected", name);
  177. return;
  178. }
  179. if( left->nd_right ) {
  180. node_error(expp,
  181. "\"%s\": filevariable can't have a width", name);
  182. return;
  183. }
  184. file = expp;
  185. arg = arg->nd_right;
  186. }
  187. else if( !(file = ChkStdInOut(name, 1)) )
  188. return;
  189. while( arg ) {
  190. assert(arg->nd_symb == ',');
  191. if( !ChkWriteParameter(text_type, arg->nd_left, name) )
  192. return;
  193. CodeWrite(file, arg->nd_left);
  194. arg = arg->nd_right;
  195. }
  196. CodeWriteln(file);
  197. }
  198. ChkWriteParameter(filetype, arg, name)
  199. struct type *filetype;
  200. struct node *arg;
  201. char *name;
  202. {
  203. struct type *tp;
  204. char *mess = "illegal write parameter";
  205. assert(arg->nd_symb == ':');
  206. tp = BaseType(arg->nd_left->nd_type);
  207. if( filetype == text_type ) {
  208. if( !(tp == bool_type ||
  209. tp->tp_fund & (T_CHAR | T_NUMERIC | T_STRING) ||
  210. IsString(tp)) ) {
  211. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  212. return 0;
  213. }
  214. }
  215. else {
  216. if( !TstAssCompat(BaseType(filetype->next), tp) ) {
  217. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  218. return 0;
  219. }
  220. if( arg->nd_right ) {
  221. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  222. return 0;
  223. }
  224. else
  225. return 1;
  226. }
  227. /* Here we have a text-file */
  228. if( arg = arg->nd_right ) {
  229. /* Total width */
  230. assert(arg->nd_symb == ':');
  231. if( BaseType(arg->nd_left->nd_type) != int_type ) {
  232. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  233. return 0;
  234. }
  235. }
  236. else
  237. return 1;
  238. if( arg = arg->nd_right ) {
  239. /* Fractional Part */
  240. assert(arg->nd_symb == ':');
  241. if( tp != real_type ) {
  242. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  243. return 0;
  244. }
  245. if( BaseType(arg->nd_left->nd_type) != int_type ) {
  246. node_error(arg->nd_left, "\"%s\": %s", name, mess);
  247. return 0;
  248. }
  249. }
  250. return 1;
  251. }
  252. struct node *
  253. ChkStdInOut(name, st_out)
  254. char *name;
  255. {
  256. register struct def *df;
  257. register struct node *nd;
  258. if( !(df = lookup(str2idf(st_out ? output : input, 0),
  259. GlobalScope, D_INUSE)) ||
  260. !(df->df_flags & D_PROGPAR) ) {
  261. error("\"%s\": standard input/output not defined", name);
  262. return NULLNODE;
  263. }
  264. nd = MkLeaf(Def, &dot);
  265. nd->nd_def = df;
  266. nd->nd_type = df->df_type;
  267. df->df_flags |= D_USED;
  268. return nd;
  269. }
  270. CodeRead(file, arg)
  271. register struct node *file, *arg;
  272. {
  273. struct type *tp = BaseType(arg->nd_type);
  274. if( err_occurred ) return;
  275. CodeDAddress(file);
  276. if( file->nd_type == text_type ) {
  277. switch( tp->tp_fund ) {
  278. case T_CHAR:
  279. C_cal("_rdc");
  280. break;
  281. case T_INTEGER:
  282. C_cal("_rdi");
  283. break;
  284. case T_LONG:
  285. C_cal("_rdl");
  286. break;
  287. case T_REAL:
  288. C_cal("_rdr");
  289. break;
  290. default:
  291. crash("(CodeRead)");
  292. /*NOTREACHED*/
  293. }
  294. C_asp(pointer_size);
  295. C_lfr(tp->tp_size);
  296. RangeCheck(arg->nd_type, file->nd_type->next);
  297. CodeDStore(arg);
  298. }
  299. else {
  300. /* Keep the address of the file on the stack */
  301. C_dup(pointer_size);
  302. C_cal("_wdw");
  303. C_asp(pointer_size);
  304. C_lfr(pointer_size);
  305. RangeCheck(arg->nd_type, file->nd_type->next);
  306. C_loi(file->nd_type->next->tp_psize);
  307. if( tp == real_type ) {
  308. if( BaseType(file->nd_type->next) == int_type ||
  309. BaseType(file->nd_type->next) == long_type )
  310. Int2Real(file->nd_type->next->tp_psize);
  311. }
  312. CodeDStore(arg);
  313. C_cal("_get");
  314. C_asp(pointer_size);
  315. }
  316. }
  317. CodeReadln(file)
  318. struct node *file;
  319. {
  320. if( err_occurred ) return;
  321. CodeDAddress(file);
  322. C_cal("_rln");
  323. C_asp(pointer_size);
  324. }
  325. CodeWrite(file, arg)
  326. register struct node *file, *arg;
  327. {
  328. int width = 0;
  329. register arith nbpars = pointer_size;
  330. register struct node *expp = arg->nd_left;
  331. struct node *right = arg->nd_right;
  332. struct type *tp = BaseType(expp->nd_type);
  333. if( err_occurred ) return;
  334. CodeDAddress(file);
  335. CodePExpr(expp);
  336. if( file->nd_type == text_type ) {
  337. if( tp->tp_fund & (T_ARRAY | T_STRINGCONST) ) {
  338. C_loc(IsString(tp));
  339. nbpars += pointer_size + int_size;
  340. }
  341. else nbpars += tp->tp_size;
  342. if( right ) {
  343. width = 1;
  344. CodePExpr(right->nd_left);
  345. nbpars += int_size;
  346. right = right->nd_right;
  347. }
  348. switch( tp->tp_fund ) {
  349. case T_ENUMERATION: /* boolean */
  350. C_cal(width ? "_wsb" : "_wrb");
  351. break;
  352. case T_CHAR:
  353. C_cal(width ? "_wsc" : "_wrc");
  354. break;
  355. case T_INTEGER:
  356. C_cal(width ? "_wsi" : "_wri");
  357. break;
  358. case T_LONG:
  359. C_cal(width ? "_wsl" : "_wrl");
  360. break;
  361. case T_REAL:
  362. if( right ) {
  363. CodePExpr(right->nd_left);
  364. nbpars += int_size;
  365. C_cal("_wrf");
  366. }
  367. else C_cal(width ? "_wsr" : "_wrr");
  368. break;
  369. case T_ARRAY:
  370. case T_STRINGCONST:
  371. C_cal(width ? "_wss" : "_wrs");
  372. break;
  373. case T_STRING:
  374. C_cal(width ? "_wsz" : "_wrz");
  375. break;
  376. default:
  377. crash("(CodeWrite)");
  378. /*NOTREACHED*/
  379. }
  380. C_asp(nbpars);
  381. }
  382. else {
  383. if( file->nd_type->next == real_type && tp == int_type )
  384. Int2Real(int_size);
  385. else if( file->nd_type->next == real_type && tp == long_type )
  386. Int2Real(long_size);
  387. CodeDAddress(file);
  388. C_cal("_wdw");
  389. C_asp(pointer_size);
  390. C_lfr(pointer_size);
  391. C_sti(file->nd_type->next->tp_psize);
  392. C_cal("_put");
  393. C_asp(pointer_size);
  394. }
  395. }
  396. CodeWriteln(file)
  397. register struct node *file;
  398. {
  399. if( err_occurred ) return;
  400. CodeDAddress(file);
  401. C_cal("_wln");
  402. C_asp(pointer_size);
  403. }