- int c;
- int desc;
- FILE *stream;
- int line;
- char *msg;
- struct cleanup *cleanups;
-
- line = last_line_listed - 1;
-
- msg = (char *) re_comp (regex);
- if (msg)
- error (("%s"), msg);
-
- if (current_source_symtab == 0)
- select_source_symtab (0);
-
- desc = open_source_file (current_source_symtab);
- if (desc < 0)
- perror_with_name (symtab_to_filename_for_display (current_source_symtab));
- cleanups = make_cleanup_close (desc);
-
- if (current_source_symtab->line_charpos == 0)
- find_source_lines (current_source_symtab, desc);
-
- if (line < 1 || line > current_source_symtab->nlines)
- error (_("Expression not found"));
-
- if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
- perror_with_name (symtab_to_filename_for_display (current_source_symtab));
-
- discard_cleanups (cleanups);
- stream = fdopen (desc, FDOPEN_MODE);
- clearerr (stream);
- cleanups = make_cleanup_fclose (stream);
- while (line > 1)
- {
-/* FIXME!!! We walk right off the end of buf if we get a long line!!! */
- char buf[4096]; /* Should be reasonable??? */
- char *p = buf;
-
- c = fgetc (stream);
- if (c == EOF)
- break;
- do
- {
- *p++ = c;
- }
- while (c != '\n' && (c = fgetc (stream)) >= 0);
-
- /* Remove the \r, if any, at the end of the line, otherwise
- regular expressions that end with $ or \n won't work. */
- if (p - buf > 1 && p[-2] == '\r')
- {
- p--;
- p[-1] = '\n';
- }
-
- /* We now have a source line in buf; null terminate and match. */
- *p = 0;
- if (re_exec (buf) > 0)
- {
- /* Match! */
- do_cleanups (cleanups);
- print_source_lines (current_source_symtab, line, line + 1, 0);
- set_internalvar_integer (lookup_internalvar ("_"), line);
- current_source_line = max (line - lines_to_list / 2, 1);
- return;
- }
- line--;
- if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
- {
- const char *filename;
-
- do_cleanups (cleanups);
- filename = symtab_to_filename_for_display (current_source_symtab);
- perror_with_name (filename);
- }
- }