rmach.c 8.6 KB

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