readwrite.c 7.7 KB

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