main.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /* Copyright (c) 1982 Regents of the University of California */
  2. static char sccsid[] = "@(#)main.c 1.6 8/16/83";
  3. /*
  4. * Debugger main routine.
  5. */
  6. #include "defs.h"
  7. #include <setjmp.h>
  8. #include <signal.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include "main.h"
  12. #include "symbols.h"
  13. #include "scanner.h"
  14. #include "process.h"
  15. #include "source.h"
  16. #include "object.h"
  17. #include "mappings.h"
  18. #ifndef public
  19. #define isterm(file) (interactive or isatty(fileno(file)))
  20. #include <sgtty.h>
  21. typedef struct {
  22. struct sgttyb sgttyb;
  23. struct tchars tchars;
  24. int lmode;
  25. struct ltchars ltchars;
  26. int fcntl_flags;
  27. int fcntl_owner;
  28. } Ttyinfo;
  29. #endif
  30. public Boolean coredump; /* true if using a core dump */
  31. public Boolean runfirst; /* run program immediately */
  32. public Boolean interactive; /* standard input IS a terminal */
  33. public Boolean lexdebug; /* trace yylex return values */
  34. public Boolean tracebpts; /* trace create/delete breakpoints */
  35. public Boolean traceexec; /* trace process execution */
  36. public Boolean tracesyms; /* print symbols as their read */
  37. public File corefile; /* File id of core dump */
  38. #define FIRST_TIME 0 /* initial value setjmp returns */
  39. private Boolean initdone = false; /* true if initialization done */
  40. private jmp_buf env; /* setjmp/longjmp data */
  41. private char outbuf[BUFSIZ]; /* standard output buffer */
  42. private char namebuf[512]; /* possible name of object file */
  43. private int firstarg; /* first program argument (for -r) */
  44. private Ttyinfo ttyinfo;
  45. private catchintr();
  46. /*
  47. * Main program.
  48. */
  49. main(argc, argv)
  50. int argc;
  51. String argv[];
  52. {
  53. register Integer i;
  54. extern String date;
  55. cmdname = argv[0];
  56. catcherrs();
  57. onsyserr(EINTR, nil);
  58. setbuf(stdout, outbuf);
  59. printf("dbx version of %s.\nType 'help' for help.\n", date);
  60. fflush(stdout);
  61. scanargs(argc, argv);
  62. language_init();
  63. symbols_init();
  64. process_init();
  65. if (runfirst) {
  66. if (setjmp(env) == FIRST_TIME) {
  67. arginit();
  68. for (i = firstarg; i < argc; i++) {
  69. newarg(argv[i]);
  70. }
  71. run();
  72. /* NOTREACHED */
  73. } else {
  74. runfirst = false;
  75. }
  76. } else {
  77. init();
  78. }
  79. setjmp(env);
  80. restoretty(stdout, &ttyinfo);
  81. signal(SIGINT, catchintr);
  82. yyparse();
  83. putchar('\n');
  84. quit(0);
  85. }
  86. /*
  87. * Initialize the world, including setting initial input file
  88. * if the file exists.
  89. */
  90. public init()
  91. {
  92. File f;
  93. String home;
  94. char buf[100];
  95. extern String getenv();
  96. savetty(stdout, &ttyinfo);
  97. enterkeywords();
  98. scanner_init();
  99. if (not coredump and not runfirst) {
  100. start(nil, nil, nil);
  101. }
  102. printf("reading symbolic information ...");
  103. fflush(stdout);
  104. readobj(objname);
  105. printf("\n");
  106. fflush(stdout);
  107. if (coredump) {
  108. curfunc = whatblock(pc);
  109. } else {
  110. curfunc = program;
  111. }
  112. bpinit();
  113. f = fopen(initfile, "r");
  114. if (f != nil) {
  115. fclose(f);
  116. setinput(initfile);
  117. } else {
  118. home = getenv("HOME");
  119. if (home != nil) {
  120. sprintf(buf, "%s/%s", home, initfile);
  121. f = fopen(buf, "r");
  122. if (f != nil) {
  123. fclose(f);
  124. setinput(strdup(buf));
  125. }
  126. }
  127. }
  128. initdone = true;
  129. }
  130. /*
  131. * Re-initialize the world, first de-allocating all storage.
  132. * This is necessary when the symbol information must be re-read
  133. * from the object file when it has changed.
  134. *
  135. * Before "forgetting" things, we save the current tracing/breakpoint
  136. * information to a temp file. Then after re-creating the world,
  137. * we read the temp file as commands. This isn't always the right thing;
  138. * if a procedure that was being traced is deleted, an error message
  139. * will be generated.
  140. *
  141. * If the argument vector is not nil, then this is re-initialize is being
  142. * done in preparation for running the program. Since we want to process
  143. * the commands in the temp file before running the program, we add the
  144. * run command at the end of the temp file. In this case, reinit longjmps
  145. * back to parsing rather than returning.
  146. */
  147. public reinit(argv, infile, outfile)
  148. String *argv;
  149. String infile;
  150. String outfile;
  151. {
  152. register Integer i;
  153. String tmpfile;
  154. extern String mktemp();
  155. tmpfile = mktemp("/tmp/dbxXXXX");
  156. setout(tmpfile);
  157. status();
  158. print_alias(nil);
  159. if (argv != nil) {
  160. printf("run");
  161. for (i = 1; argv[i] != nil; i++) {
  162. printf(" %s", argv[i]);
  163. }
  164. if (infile != nil) {
  165. printf(" < %s", infile);
  166. }
  167. if (outfile != nil) {
  168. printf(" > %s", outfile);
  169. }
  170. putchar('\n');
  171. }
  172. unsetout();
  173. bpfree();
  174. objfree();
  175. process_init();
  176. enterkeywords();
  177. scanner_init();
  178. readobj(objname);
  179. bpinit();
  180. fflush(stdout);
  181. setinput(tmpfile);
  182. unlink(tmpfile);
  183. if (argv != nil) {
  184. longjmp(env, 1);
  185. /* NOTREACHED */
  186. }
  187. }
  188. /*
  189. * After a non-fatal error we jump back to command parsing.
  190. */
  191. public erecover()
  192. {
  193. if (initdone) {
  194. gobble();
  195. longjmp(env, 1);
  196. }
  197. }
  198. /*
  199. * This routine is called when an interrupt occurs.
  200. */
  201. private catchintr()
  202. {
  203. putchar('\n');
  204. longjmp(env, 1);
  205. }
  206. /*
  207. * Scan the argument list.
  208. */
  209. private scanargs(argc, argv)
  210. int argc;
  211. String argv[];
  212. {
  213. register int i, j;
  214. register Boolean foundfile;
  215. register File f;
  216. char *tmp;
  217. runfirst = false;
  218. interactive = false;
  219. lexdebug = false;
  220. tracebpts = false;
  221. traceexec = false;
  222. tracesyms = false;
  223. foundfile = false;
  224. corefile = nil;
  225. coredump = true;
  226. sourcepath = list_alloc();
  227. list_append(list_item("."), nil, sourcepath);
  228. i = 1;
  229. while (i < argc and (not foundfile or (corefile == nil and not runfirst))) {
  230. if (argv[i][0] == '-') {
  231. if (streq(argv[i], "-I")) {
  232. ++i;
  233. if (i >= argc) {
  234. fatal("missing directory for -I");
  235. }
  236. list_append(list_item(argv[i]), nil, sourcepath);
  237. } else {
  238. for (j = 1; argv[i][j] != '\0'; j++) {
  239. setoption(argv[i][j]);
  240. }
  241. }
  242. } else if (not foundfile) {
  243. objname = argv[i];
  244. foundfile = true;
  245. } else if (coredump and corefile == nil) {
  246. corefile = fopen(argv[i], "r");
  247. if (corefile == nil) {
  248. coredump = false;
  249. }
  250. }
  251. ++i;
  252. }
  253. if (i < argc and not runfirst) {
  254. fatal("extraneous argument %s", argv[i]);
  255. }
  256. firstarg = i;
  257. if (not foundfile and isatty(0)) {
  258. printf("enter object file name (default is `%s'): ", objname);
  259. fflush(stdout);
  260. gets(namebuf);
  261. if (namebuf[0] != '\0') {
  262. objname = namebuf;
  263. }
  264. }
  265. f = fopen(objname, "r");
  266. if (f == nil) {
  267. fatal("can't read %s", objname);
  268. } else {
  269. fclose(f);
  270. }
  271. if (rindex(objname, '/') != nil) {
  272. tmp = strdup(objname);
  273. *(rindex(tmp, '/')) = '\0';
  274. list_append(list_item(tmp), nil, sourcepath);
  275. }
  276. if (coredump and corefile == nil) {
  277. corefile = fopen("core", "r");
  278. if (corefile == nil) {
  279. coredump = false;
  280. }
  281. }
  282. }
  283. /*
  284. * Take appropriate action for recognized command argument.
  285. */
  286. private setoption(c)
  287. char c;
  288. {
  289. switch (c) {
  290. case 'r': /* run program before accepting commands */
  291. runfirst = true;
  292. coredump = false;
  293. break;
  294. case 'i':
  295. interactive = true;
  296. break;
  297. case 'b':
  298. tracebpts = true;
  299. break;
  300. case 'e':
  301. traceexec = true;
  302. break;
  303. case 's':
  304. tracesyms = true;
  305. break;
  306. case 'l':
  307. # ifdef LEXDEBUG
  308. lexdebug = true;
  309. # else
  310. fatal("\"-l\" only applicable when compiled with LEXDEBUG");
  311. # endif
  312. break;
  313. default:
  314. fatal("unknown option '%c'", c);
  315. }
  316. }
  317. /*
  318. * Save/restore the state of a tty.
  319. */
  320. public savetty(f, t)
  321. File f;
  322. Ttyinfo *t;
  323. {
  324. gtty(fileno(f), &t->sgttyb);
  325. ioctl(fileno(f), TIOCGETC, &t->tchars);
  326. ioctl(fileno(f), TIOCLGET, &t->lmode);
  327. ioctl(fileno(f), TIOCGLTC, &t->ltchars);
  328. t->fcntl_flags = fcntl(fileno(f), F_GETFL);
  329. t->fcntl_owner = fcntl(fileno(f), F_GETOWN);
  330. }
  331. public restoretty(f, t)
  332. File f;
  333. Ttyinfo *t;
  334. {
  335. ioctl(fileno(f), TIOCSETN, &t->sgttyb); /* instead of stty --saj */
  336. ioctl(fileno(f), TIOCSETC, &t->tchars);
  337. ioctl(fileno(f), TIOCLSET, &t->lmode);
  338. ioctl(fileno(f), TIOCSLTC, &t->ltchars);
  339. fcntl(fileno(f), F_SETFL, t->fcntl_flags);
  340. fcntl(fileno(f), F_SETOWN, t->fcntl_owner);
  341. }
  342. /*
  343. * Exit gracefully.
  344. */
  345. public quit(r)
  346. Integer r;
  347. {
  348. exit(r);
  349. }