rmach.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. *
  5. */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "ack.h"
  9. #include <em_path.h>
  10. #include "list.h"
  11. #include "trans.h"
  12. #include "grows.h"
  13. #include "dmach.h"
  14. #include "data.h"
  15. #include <stdio.h>
  16. /************************************************************************/
  17. /* */
  18. /* Read machine definitions and transformations */
  19. /* */
  20. /************************************************************************/
  21. #define COMMENT '#'
  22. #define VAR "var"
  23. #define PASS "name"
  24. #define IN "from"
  25. #define OUT "to"
  26. #define RES "outfile"
  27. #define PROG "program"
  28. #define MAPF "mapflag"
  29. #define ARGS "args"
  30. #define STD_IN "stdin"
  31. #define STD_OUT "stdout"
  32. #define PREP "prep"
  33. #define OPT "optimizer"
  34. #define LINKER "linker"
  35. #define COMBINER "combiner"
  36. #define PRIO "priority"
  37. #define RUNT "rts"
  38. #define NEEDT "need"
  39. #define CALL "callname"
  40. #define END "end"
  41. static char *ty_name ;
  42. static char *bol ;
  43. static char *inname ;
  44. void setlist(char *name)
  45. {
  46. /* Name is sought in the internal tables,
  47. if not present, the a file of that name is sought
  48. in first the current and then the EM Lib directory
  49. */
  50. inname=name ;
  51. open_in(name) ;
  52. while ( getln() ) {
  53. if ( strcmp(VAR,ty_name)==0 ) {
  54. doassign(bol,(char *)0,0) ;
  55. } else
  56. if ( strcmp(CALL,ty_name)==0 ) {
  57. if ( callname && strcmp(bol,callname)==0 ) {
  58. callname= (char *)0 ;
  59. #ifdef DEBUG
  60. if ( debug>=3 ) {
  61. vprint("found call name\n");
  62. }
  63. #endif
  64. }
  65. } else
  66. if ( strcmp(PASS,ty_name)==0 ) {
  67. intrf() ;
  68. } else
  69. error("unknown keyword %s",ty_name) ;
  70. }
  71. close_in();
  72. #ifdef DEBUG
  73. if ( debug>=3 ) vprint("End %s\n",name) ;
  74. #endif
  75. }
  76. static int inoptlist(char *nm)
  77. {
  78. register char *p=Optlist ;
  79. while ( p && *p ) {
  80. register char *q=nm ;
  81. while ( *q!='\0' && *q++==*p ) p++ ;
  82. if ( *q=='\0' && ( *p=='\0' || *p==',' ) ) return 1 ;
  83. while ( *p!='\0' && *p++!=',' ) /* nothing */ ;
  84. }
  85. return 0;
  86. }
  87. void intrf()
  88. {
  89. register trf *new ;
  90. growstring bline ;
  91. int twice ;
  92. int name_seen=0 ;
  93. new= (trf *)getcore(sizeof *new) ;
  94. new->t_name= keeps(bol) ;
  95. for (;;) {
  96. if ( !getln() ) {
  97. fuerror("unexpected EOF on %s",inname) ;
  98. }
  99. twice= NO ;
  100. if ( strcmp(ty_name,IN)==0 ) {
  101. if ( new->t_in ) twice=YES ;
  102. new->t_in= keeps(bol);
  103. } else
  104. if ( strcmp(ty_name,OUT)==0 ) {
  105. if ( new->t_out ) twice=YES ;
  106. new->t_out= keeps(bol);
  107. } else
  108. if ( strcmp(ty_name,PROG)==0 ) {
  109. if ( new->t_prog ) twice=YES ;
  110. bline= scanb(bol); /* Scan for \ */
  111. new->t_prog= gr_final(&bline);
  112. } else
  113. if ( strcmp(ty_name,MAPF)==0 ) {
  114. /* First read the mapflags line
  115. and scan for backslashes */
  116. bline= scanb(bol) ;
  117. l_add(&new->t_mapf,gr_final(&bline)) ;
  118. } else
  119. if ( strcmp(ty_name,ARGS)==0 ) {
  120. if ( new->t_argd ) twice=YES ;
  121. bline= scanb(bol) ;
  122. new->t_argd= keeps(gr_start(bline)) ;
  123. gr_throw(&bline) ;
  124. } else
  125. if ( strcmp(ty_name,STD_IN)==0 ) {
  126. if ( new->t_stdin ) twice=YES ;
  127. new->t_stdin= YES ;
  128. } else
  129. if ( strcmp(ty_name,STD_OUT)==0 ) {
  130. if ( new->t_stdout ) twice=YES ;
  131. new->t_stdout= YES ;
  132. } else
  133. if ( strcmp(ty_name,PREP)==0 ) {
  134. if ( strcmp(bol,"always")==0 ) {
  135. if ( new->t_prep ) twice=YES ;
  136. new->t_prep=YES ;
  137. } else
  138. if ( strcmp(bol,"cond")==0 ) {
  139. if ( new->t_prep ) twice=YES ;
  140. new->t_prep=MAYBE ;
  141. } else
  142. if ( strcmp(bol,"is")==0 ) {
  143. if ( new->t_isprep ) twice=YES ;
  144. new->t_isprep= YES ;
  145. } else
  146. {
  147. fuerror("illegal preprocessor spec in %s: %s",
  148. inname,bol) ;
  149. }
  150. } else
  151. if ( strcmp(ty_name,OPT)==0 ) {
  152. if ( new->t_optim ) twice=YES ;
  153. new->t_optim= atoi(bol) ;
  154. if (new->t_optim <= 0) new->t_optim = 1;
  155. } else
  156. if ( strcmp(ty_name,LINKER)==0 ) {
  157. if ( new->t_linker ) twice=YES ;
  158. new->t_linker= YES ;
  159. new->t_combine= YES ;
  160. } else
  161. if ( strcmp(ty_name,COMBINER)==0 ) {
  162. if ( new->t_combine ) twice=YES ;
  163. new->t_combine= YES ;
  164. } else
  165. if ( strcmp(ty_name,PRIO)==0 ) {
  166. new->t_priority= atoi(bol) ;
  167. } else
  168. if ( strcmp(ty_name,RUNT)==0 ) {
  169. if ( new->t_rts ) twice=YES ;
  170. new->t_rts= keeps(bol) ;
  171. } else
  172. if ( strcmp(ty_name,NEEDT)==0 ) {
  173. if ( new->t_needed ) twice=YES ;
  174. new->t_needed= keeps(bol) ;
  175. } else
  176. if ( strcmp(ty_name,RES)==0 ) {
  177. if ( new->t_outfile ) twice=YES ;
  178. new->t_outfile= keeps(bol) ;
  179. } else
  180. if ( strcmp(ty_name,CALL)==0 ) {
  181. if ( callname && strcmp(bol,callname)==0 ) {
  182. name_seen=1 ;
  183. callname= (char *)0 ;
  184. #ifdef DEBUG
  185. if ( debug>=3 ) {
  186. vprint("found call name in %s\n",
  187. new->t_name) ;
  188. }
  189. #endif
  190. }
  191. } else
  192. if ( strcmp(ty_name,END)==0 ) {
  193. break ;
  194. } else {
  195. fuerror("illegal keyword %s %s",ty_name,bol);
  196. }
  197. if ( twice ) {
  198. werror("%s: specified twice for %s",
  199. ty_name, new->t_name) ;
  200. }
  201. }
  202. if ( ! ( new->t_name && new->t_out && new->t_prog ) ) {
  203. fuerror("insufficient specification for %s in %s",
  204. new->t_name,inname) ;
  205. }
  206. if ( ! new->t_argd ) new->t_argd="" ;
  207. /* Warning, side effect */
  208. if ( name_seen && new->t_rts ) {
  209. if ( rts && strcmp(rts,new->t_rts)!=0 ) {
  210. error("Attempt to use two run-time systems, %s and %s",
  211. rts, new->t_rts) ;
  212. }
  213. rts= new->t_rts ;
  214. keephead(rts) ; keeptail(rts) ;
  215. }
  216. #ifdef DEBUG
  217. if ( debug>=3 ) {
  218. register list_elem *elem ;
  219. vprint("%s: from %s to %s '%s'\n",
  220. new->t_name,new->t_in ? new->t_in : "(null)",new->t_out,new->t_prog) ;
  221. vprint("\targs: ") ; prns(new->t_argd) ;
  222. scanlist( l_first(new->t_mapf), elem ) {
  223. vprint("\t%s\n",l_content(*elem)) ;
  224. }
  225. if ( new->t_rts ) vprint("\trts: %s\n",new->t_rts) ;
  226. if ( new->t_needed ) vprint("\tneeded: %s\n",new->t_needed) ;
  227. }
  228. #endif
  229. if ( new->t_optim &&
  230. ( new->t_optim <= Optlevel || inoptlist(new->t_name) ) ) {
  231. new->t_optim = Optlevel;
  232. }
  233. l_add(&tr_list,(char *)new) ;
  234. }
  235. /************************** IO from core or file *******************/
  236. static int incore ;
  237. static growstring rline ;
  238. static FILE *infile ;
  239. static char *inptr ;
  240. char *em_dir = EM_DIR;
  241. void open_in(char *name)
  242. {
  243. register dmach *cmac ;
  244. gr_init(&rline) ;
  245. for ( cmac= massoc ; cmac->ma_index!= -1 ; cmac++ ) {
  246. if ( strcmp(name,cmac->ma_name)==0 ) {
  247. incore=YES ;
  248. inptr= &intable[cmac->ma_index] ;
  249. return ;
  250. }
  251. }
  252. /* Not in core */
  253. incore= NO ;
  254. /* Try to read EM_DIR/lib/MACH/descr */
  255. gr_cat(&rline,em_dir) ;
  256. gr_cat(&rline,"/lib/") ; gr_cat(&rline,name) ;
  257. gr_cat(&rline,"/descr") ;
  258. infile= fopen(gr_start(rline),"r") ;
  259. if ( !infile ) {
  260. gr_throw(&rline) ;
  261. gr_cat(&rline,em_dir) ; gr_cat(&rline,"/") ;
  262. gr_cat(&rline,ACK_PATH); gr_cat(&rline,"/") ;
  263. gr_cat(&rline,name) ;
  264. infile= fopen(gr_start(rline),"r") ;
  265. }
  266. if ( !infile ) {
  267. infile= fopen(name,"r") ;
  268. }
  269. if ( infile==NULL ) {
  270. fuerror("Cannot find description for %s",name) ;
  271. }
  272. }
  273. void close_in()
  274. {
  275. if ( !incore ) fclose(infile) ;
  276. gr_throw(&rline) ;
  277. }
  278. char *readline()
  279. {
  280. /* Get a line from the input,
  281. return 0 if at end,
  282. The line is stored in a volatile buffer,
  283. a pointer to the line is returned.
  284. */
  285. register int nchar ;
  286. enum { BOL, ESCAPE, SKIPPING, MOL } state = BOL ;
  287. gr_throw(&rline) ;
  288. for (;;) {
  289. nchar= getinchar() ;
  290. if ( nchar==EOF ) {
  291. if ( state!=BOL ) {
  292. werror("incomplete line in %s", inname) ;
  293. }
  294. return 0 ;
  295. }
  296. if ( state==SKIPPING ) {
  297. if ( nchar=='\n' ) {
  298. state= MOL ;
  299. } else {
  300. continue ;
  301. }
  302. }
  303. if ( state==ESCAPE ) {
  304. switch( nchar ) {
  305. case '\n' :
  306. break ;
  307. default :
  308. gr_add(&rline,BSLASH) ;
  309. case COMMENT :
  310. case BSLASH :
  311. gr_add(&rline,nchar) ;
  312. break ;
  313. }
  314. state= MOL ;
  315. continue ;
  316. }
  317. switch ( nchar ) {
  318. case '\n' : gr_add(&rline,0) ;
  319. return gr_start(rline) ;
  320. case COMMENT : state= SKIPPING ;
  321. break ;
  322. case BSLASH : state= ESCAPE ;
  323. break ;
  324. default : gr_add(&rline,nchar) ;
  325. state= MOL ;
  326. }
  327. }
  328. }
  329. int getinchar()
  330. {
  331. int token ;
  332. if ( incore ) {
  333. if ( *inptr==0 ) return EOF ;
  334. return *inptr++ ;
  335. }
  336. token= getc(infile) ;
  337. if ( (token>=0177 || token <=0 ) && token !=EOF ) {
  338. fuerror("Non-ascii character in description file %s",inname);
  339. }
  340. return token ;
  341. }
  342. int getln()
  343. {
  344. char *c_ptr ;
  345. do {
  346. if ( (c_ptr=readline())==(char *)0 ) return 0 ;
  347. ty_name= skipblank(c_ptr) ;
  348. } while ( *ty_name==0 ) ;
  349. c_ptr= firstblank(ty_name) ;
  350. if ( *c_ptr ) {
  351. *c_ptr++ =0 ;
  352. c_ptr= skipblank(c_ptr) ;
  353. }
  354. bol= c_ptr ;
  355. return 1 ;
  356. }