📄 fixincl.c
字号:
}/* * * * * * * * * * * * * quoted_file_exists Make sure that a file exists before we emit the file name. If we emit the name, our invoking shell will try to copy a non-existing file into the destination directory. */intquoted_file_exists (pz_src_path, pz_file_path, pz_file) char* pz_src_path; char* pz_file_path; char* pz_file;{ char z[ MAXPATHLEN ]; char* pz; sprintf (z, "%s/%s/", pz_src_path, pz_file_path); pz = z + strlen ( z ); for (;;) { char ch = *pz_file++; if (! isgraph( ch )) return 0; if (ch == '"') break; *pz++ = ch; } *pz = '\0'; { struct stat s; if (stat (z, &s) != 0) return 0; return S_ISREG( s.st_mode ); }}/* * * * * * * * * * * * * * extract_quoted_files The syntax, `#include "file.h"' specifies that the compiler is to search the local directory of the current file before the include list. Consequently, if we have modified a header and stored it in another directory, any files that are included by that modified file in that fashion must also be copied into this new directory. This routine finds those flavors of #include and for each one found emits a triple of: 1. source directory of the original file 2. the relative path file name of the #includ-ed file 3. the full destination path for this file Input: the text of the file, the file name and a pointer to the match list where the match information was stored. Result: internally nothing. The results are written to stdout for interpretation by the invoking shell */voidextract_quoted_files (pz_data, pz_file_name, p_re_match) char *pz_data; const char *pz_file_name; regmatch_t *p_re_match;{ char *pz_dir_end = strrchr (pz_file_name, '/'); char *pz_incl_quot = pz_data; fprintf (stderr, "Quoted includes in %s\n", pz_file_name); /* Set "pz_file_name" to point to the containing subdirectory of the source If there is none, then it is in our current directory, ".". */ if (pz_dir_end == (char *) NULL) pz_file_name = "."; else *pz_dir_end = '\0'; for (;;) { pz_incl_quot += p_re_match->rm_so; /* Skip forward to the included file name */ while (isspace (*pz_incl_quot)) pz_incl_quot++; while (isspace (*++pz_incl_quot)) ; pz_incl_quot += sizeof ("include") - 1; while (*pz_incl_quot++ != '"') ; if (quoted_file_exists (pz_src_dir, pz_file_name, pz_incl_quot)) { /* Print the source directory and the subdirectory of the file in question. */ printf ("%s %s/", pz_src_dir, pz_file_name); pz_dir_end = pz_incl_quot; /* Append to the directory the relative path of the desired file */ while (*pz_incl_quot != '"') putc (*pz_incl_quot++, stdout); /* Now print the destination directory appended with the relative path of the desired file */ printf (" %s/%s/", pz_dest_dir, pz_file_name); while (*pz_dir_end != '"') putc (*pz_dir_end++, stdout); /* End of entry */ putc ('\n', stdout); } /* Find the next entry */ if (regexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0) break; }}/* * * * * * * * * * * * * This loop should only cycle for 1/2 of one loop. "chain_open" starts a process that uses "read_fd" as its stdin and returns the new fd this process will use for stdout. */intstart_fixer (read_fd, p_fixd, pz_file_name) int read_fd; tFixDesc* p_fixd; char* pz_file_name;{ tSCC z_err[] = "Error %d (%s) starting filter process for %s\n"; tCC* pz_cmd_save; char* pz_cmd; if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0) pz_cmd = (char*)NULL; else { tSCC z_cmd_fmt[] = "file='%s'\n%s"; pz_cmd = (char*)xmalloc (strlen (p_fixd->patch_args[2]) + sizeof( z_cmd_fmt ) + strlen( pz_file_name )); sprintf (pz_cmd, z_cmd_fmt, pz_file_name, p_fixd->patch_args[2]); pz_cmd_save = p_fixd->patch_args[2]; p_fixd->patch_args[2] = pz_cmd; } for (;;) { static int failCt = 0; int fd; fd = chain_open (read_fd, (t_pchar *) p_fixd->patch_args, (process_chain_head == -1) ? &process_chain_head : (pid_t *) NULL); if (fd != -1) { read_fd = fd; break; } fprintf (stderr, z_err, errno, strerror (errno), p_fixd->fix_name); if ((errno != EAGAIN) || (++failCt > 10)) exit (EXIT_FAILURE); sleep (1); } if (pz_cmd != (char*)NULL) { free ((void*)pz_cmd); p_fixd->patch_args[2] = pz_cmd_save; } return read_fd;}/* * * * * * * * * * * * * Process the potential fixes for a particular include file. Input: the original text of the file and the file's name Result: none. A new file may or may not be created. */voidprocess (pz_data, pz_file_name) char *pz_data; const char *pz_file_name;{ static char env_current_file[1024]; tFixDesc *p_fixd = fixDescList; int todo_ct = FIX_COUNT; int read_fd = -1; int num_children = 0; process_chain_head = NOPROCESS; fprintf (stderr, "%-50s \r", pz_file_name ); /* For every fix in our fix list, ... */ for (; todo_ct > 0; p_fixd++, todo_ct--) { tTestDesc *p_test; int test_ct; if (p_fixd->fd_flags & FD_SKIP_TEST) continue; /* IF there is a file name restriction, THEN ensure the current file name matches one in the pattern */ if (p_fixd->file_list != (char *) NULL) { const char *pz_fname = pz_file_name; const char *pz_scan = p_fixd->file_list; size_t name_len; while ((pz_fname[0] == '.') && (pz_fname[1] == '/')) pz_fname += 2; name_len = strlen (pz_fname); for (;;) { pz_scan = strstr (pz_scan + 1, pz_fname); /* IF we can't match the string at all, THEN bail */ if (pz_scan == (char *) NULL) goto next_fix; /* IF the match is surrounded by the '|' markers, THEN we found a full match -- time to run the tests */ if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|')) break; } } /* FOR each test, see if it fails. IF it does fail, then we go on to the next test */ for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct; test_ct-- > 0; p_test++) {#ifdef DEBUG_TEST static const char z_test_fail[] = "%16s test %2d failed for %s\n";#endif switch (p_test->type) { case TT_TEST: if (!SUCCESSFUL (test_test (p_test, pz_file_name))) {#ifdef DEBUG_TEST fprintf (stderr, z_test_fail, p_fixd->fix_name, p_fixd->test_ct - test_ct, pz_file_name);#endif goto next_fix; } break; case TT_EGREP: if (!SUCCESSFUL (egrep_test (pz_data, p_test))) {#ifdef DEBUG_TEST fprintf (stderr, z_test_fail, p_fixd->fix_name, p_fixd->test_ct - test_ct, pz_file_name);#endif goto next_fix; } break; case TT_NEGREP: if (SUCCESSFUL (egrep_test (pz_data, p_test))) {#ifdef DEBUG_TEST fprintf (stderr, z_test_fail, p_fixd->fix_name, p_fixd->test_ct - test_ct, pz_file_name);#endif goto next_fix; } break; } } fprintf (stderr, "Applying %-24s to %s\n", p_fixd->fix_name, pz_file_name); /* IF we do not have a read pointer, THEN this is the first fix for the current file. Open the source file. That will be used as stdin for the first fix. Any subsequent fixes will use the stdout descriptor of the previous fix as its stdin. */ if (read_fd == -1) { read_fd = open (pz_file_name, O_RDONLY); if (read_fd < 0) { fprintf (stderr, "Error %d (%s) opening %s\n", errno, strerror (errno), pz_file_name); exit (EXIT_FAILURE); } } read_fd = start_fixer (read_fd, p_fixd, pz_file_name); num_children++; next_fix: ; } /* IF after all the tests we did not start any patch programs, THEN quit now. */ if (read_fd < 0) return; /* OK. We have work to do. Read back in the output of the filtering chain. Compare each byte as we read it with the contents of the original file. As soon as we find any difference, we will create the output file, write out all the matched text and then copy any remaining data from the output of the filter chain. */ { FILE *in_fp = fdopen (read_fd, "r"); FILE *out_fp = (FILE *) NULL; char *pz_cmp = pz_data; for (;;) { int ch; ch = getc (in_fp); if (ch == EOF) break; /* IF we are emitting the output THEN emit this character, too. */ if (out_fp != (FILE *) NULL) putc (ch, out_fp); /* ELSE if this character does not match the original, THEN now is the time to start the output. */ else if (ch != *pz_cmp) { out_fp = create_file (pz_file_name); /* IF there are matched data, write it all now. */ if (pz_cmp != pz_data) { char c = *pz_cmp; *pz_cmp = NUL; fputs (pz_data, out_fp); *pz_cmp = c; } /* Emit the current unmatching character */ putc (ch, out_fp); } else /* ELSE the character matches. Advance the compare ptr */ pz_cmp++; } /* IF we created the output file, ... */ if (out_fp != (FILE *) NULL) { regmatch_t match; /* Close the file and see if we have to worry about `#include "file.h"' constructs. */ fclose (out_fp); if (regexec (&incl_quote_re, pz_data, 1, &match, 0) == 0) extract_quoted_files (pz_data, pz_file_name, &match); } fclose (in_fp); } close (read_fd); /* probably redundant, but I'm paranoid */ /* Wait for child processes created by chain_open() to avoid creating zombies. */ while (--num_children >= 0) wait ((int *) NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -