rmach.c 8.7 KB

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