⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scc.c

📁 CVS的WINDOWS版本 我们编译的平台不同 刚才的是在LINUX下的 现在是WIN下的
💻 C
字号:
/* This file was written by Jim Kingdon, and is hereby placed   in the public domain.  */#include <Wtypes.h>#include <stdio.h>#include <direct.h> /* For chdir */#include "pubscc.h"/* We get to put whatever we want here, and the caller will pass it   to us, so we don't need any global variables.  This is the   "void *context_arg" argument to most of the Scc* functions.  */struct context {    FILE *debuglog;    /* Value of the CVSROOT we are currently working with (that is, the       "open project" in SCC terminology), malloc'd, or NULL if there is       no project currently open.  */    char *root;    /* Local directory (working directory in CVS parlance).  */    char *local;    SCC_outproc outproc;};/* In addition to context_arg, most of the Scc* functions take a   "HWND window" argument.  This is so that we can put up dialogs.   The window which is passed in is the IDE's window, which we   should use as the parent of dialogs that we put up.  */#include <windows.h>/* Report a malloc error and return the SCC_return_* value which the   caller should return to the IDE.  Probably this should be getting   the window argument too, but for the moment we don't need it.   Note that we only use this for errors which occur after the   context->outproc is set up.  */SCC_returnmalloc_error (struct context *context){    (*context->outproc) ("Out of memory\n", SCC_outproc_error);    return SCC_return_non_specific_error;}/* Return the version of the SCC spec, major version in the high word,   minor version in the low word.  */LONGSccGetVersion (void){    /* We implement version 1.1 of the spec.  */    return 0x10001;}SCC_returnSccInitialize (void **contextp, HWND window, LPSTR caller, LPSTR name,               LPLONG caps, LPSTR path, LPDWORD co_comment_len,               LPDWORD comment_len){    struct context *context;    FILE *fp;    fp = fopen ("d:\\debug.scc", "w");    if (fp == NULL)        /* Do what?  Return some error value?  */        abort ();    context = malloc (sizeof (struct context));    if (context == NULL)    {        fprintf (fp, "Out of memory\n");        fclose (fp);        /* Do what?  Return some error?  */        abort ();    }    context->debuglog = fp;    context->root = NULL;    *contextp = context;    fprintf (fp, "Made it into SccInitialize!\n");    *caps = (SCC_cap_GetProjPath	     | SCC_cap_AddFromScc	     | SCC_cap_want_outproc);    /* I think maybe this should have some more CVS-like       name, like "CVS Root", if we decide that is what       a SCC "project" is.  */    strncpy (path, "CVS Project:", SCC_max_init_path);    fprintf (fp, "Caller name is %s\n", caller);    strncpy (name, "CVS", SCC_max_name);    /* CVS has no limit on comment length.  But I suppose       we need to return a value which is small enough for       a caller to allocate a buffer this big.  Not that I       would write a caller that way, but.....  */    *co_comment_len = 8192;    *comment_len = 8192;    fflush (fp);    return SCC_return_success;}SCC_returnSccUninitialize (void *context_arg){    struct context *context = (struct context *)context_arg;    if (ferror (context->debuglog))	/* FIXME: return error value...  */    if (fclose (context->debuglog) == EOF)        /* FIXME: return error value, I think.  */        ;    free (context);    return SCC_return_success;}SCC_returnSccOpenProject (void *context_arg, HWND window, LPSTR user,		LPSTR project, LPSTR local_proj, LPSTR aux_proj,		LPSTR comment, SCC_outproc outproc,		LONG flags){    struct context *context = (struct context *)context_arg;    /* This can happen if the IDE opens a project which is not under       CVS control.  I'm not sure whether checking for aux_proj       being "" is the right way to detect this case, but it seems       it should work because I think that the source code control       system is what has control over the contents of aux_proj.  */    if (aux_proj[0] == '\0')	return SCC_return_unknown_project;    context->root = malloc (strlen (aux_proj) + 5);    if (context->root == NULL)	return SCC_return_non_specific_error;    strcpy (context->root, aux_proj);    /* Since we don't yet support creating projects, we don't       do anything with flags.  */    if (outproc == 0)    {	/* This supposedly can happen if the IDE chooses not to implement	   the outproc feature.  */	fprintf (context->debuglog, "Uh oh.  outproc is a null pointer\n");	context->root = NULL;	fflush (context->debuglog);	return SCC_return_non_specific_error;    }    context->outproc = outproc;    fprintf (context->debuglog, "SccOpenProject (aux_proj=%s)\n", aux_proj);    context->local = malloc (strlen (local_proj) + 5);    if (context->local == NULL)	return malloc_error (context);    strcpy (context->local, local_proj);    fflush (context->debuglog);    return SCC_return_success;}SCC_returnSccCloseProject (void *context_arg){    struct context *context = (struct context *)context_arg;    fprintf (context->debuglog, "SccCloseProject\n");    fflush (context->debuglog);    if (context->root != NULL)	free (context->root);    context->root = NULL;    return SCC_return_success;}/* cvs get.  */SCC_returnSccGet (void *context_arg, HWND window, LONG num_files,        LPSTR *file_names,	LONG options,	void *prov_options){    struct context *context = (struct context *)context_arg;    int i;    char *fname;    fprintf (context->debuglog, "SccGet: %d; files:", num_files);#if 1    for (i = 0; i < num_files; ++i)    {	fprintf (context->debuglog, "%s ", file_names[i]);    }#endif    fprintf (context->debuglog, "\n");    if (options & SCC_cmdopt_dir)	fprintf (context->debuglog, "  Get all\n");    /* Should be using this flag to set -R vs. -l.  */    if (options & SCC_cmdopt_recurse)	fprintf (context->debuglog, "  recurse\n");    for (i = 0; i < num_files; ++i)    {	/* As with all file names passed to us by the SCC, these	   file names are absolute pathnames.  I think they will	   tend to be paths within context->local, although I	   don't know whether there are any exceptions to that.  */	fname = file_names[i];	fprintf (context->debuglog, "%s ", fname);	/* Here we would write to the file named fname.  */    }    fprintf (context->debuglog, "\nExiting SccGet\n");    fflush (context->debuglog);    return SCC_return_success;}/* cvs edit.  */SCC_returnSccCheckout (void *context_arg, HWND window, LONG num_files,             LPSTR *file_names, LPSTR comment,	     LONG options,             void *prov_options){    struct context *context = (struct context *)context_arg;    fprintf (context->debuglog, "SccCheckout num_files=%ld\n", num_files);    fflush (context->debuglog);    /* For the moment we say that all files are not ours.  I'm not sure       whether this is ever necessary; that is, whether the IDE will call       us except where we have told the IDE that a file is under source       control.  */    /* I'm not sure what we would do if num_files > 1 and we wanted to       return different statuses for different files.  */    return SCC_return_non_scc_file;}/* cvs ci.  */SCC_returnSccCheckin (void *context_arg, HWND window, LONG num_files,            LPSTR *file_names, LPSTR comment,	    LONG options,            void *prov_options){    return SCC_return_not_supported;}/* cvs unedit.  */SCC_returnSccUncheckout (void *context_arg, HWND window, LONG num_files,               LPSTR *file_names,	       LONG options,	       void *prov_options){    return SCC_return_not_supported;}/* cvs add + cvs ci, more or less, I think (but see also   the "keep checked out" flag in options).  */SCC_returnSccAdd (void *context_arg, HWND window, LONG num_files,        LPSTR *file_names, LPSTR comment,	LONG *options,        void *prov_options){    return SCC_return_not_supported;}/* cvs rm -f + cvs ci, I think.  Should barf if SCC_REMOVE_KEEP   (or maybe just put the file there, as if the user had removed   it and then done a "copy <saved-file> <filename>".  */SCC_returnSccRemove (void *context_arg, HWND window, LONG num_files,           LPSTR *file_names, LPSTR comment,	   LONG options,           void *prov_options){    return SCC_return_not_supported;}/* mv, cvs add, cvs rm, and cvs ci, I think.  */SCC_returnSccRename (void *context_arg, HWND window, LPSTR old_name,           LPSTR new_name){    return SCC_return_not_supported;}/* If SCC_cmdopt_compare_files, SCC_cmdopt_consult_checksum, or   SCC_cmdopt_consult_timestamp, then we are supposed to silently   return a status, without providing any information directly to the   user.  For no args or checksum (which we fall back to full compare)   basically a call to No_Diff or ? in the client case.  For   timestamp, just a Classify_File.  Now, if contents not set, then   want to do a cvs diff, and preferably start up WinDiff or something   (to be determined, for now perhaps could just return text via   outproc).  */SCC_returnSccDiff (void *context_arg, HWND window, LPSTR file_name,         LONG options,	 void *prov_options){    return SCC_return_not_supported;}/* cvs log, I presume.  If we want to get fancier we could bring   up a screen more analogous to the tkCVS log window, let the user   do "cvs update -r", etc.  */SCC_returnSccHistory (void *context_arg, HWND window, LONG num_files,            LPSTR *file_names,	    LONG options,	    void *prov_options){    return SCC_return_not_supported;}/* cvs status, presumably.  */SCC_returnSccProperties (void *context_arg, HWND window, LPSTR file_name){    return SCC_return_not_supported;}/* Not sure what this should do.  The most obvious thing is some   kind of front-end to "cvs admin" but I'm not actually sure that   is the most useful thing.  */SCC_returnSccRunScc (void *context_arg, HWND window, LONG num_files,           LPSTR *file_names){    return SCC_return_not_supported;}/* Lots of things that we could do here.  Options to get/update   such as -r -D -k etc. just for starters.  Note that the terminology is   a little confusing here.  This function relates to "provider options"   (prov_options) which are a way for us to provide extra dialogs beyond   the basic ones for a particular command.  It is unrelated to "command   options" (SCC_cmdopt_*).  */SCC_returnSccGetCommandOptions (void *context_arg, HWND window,                      enum SCC_command command,                      void **prov_optionsp){    return SCC_return_not_supported;}/* Not existing CVS functionality, I don't think.   Need to be able to tell user about what files   are out there without actually getting them.  */SCC_returnSccPopulateList (void *context_arg, enum SCC_command command,                 LONG num_files,                 LPSTR *file_names, SCC_popul_proc populate,                 void *callerdat,		 LONG options){    return SCC_return_success;}/* cvs status, sort of.  */SCC_returnSccQueryInfo (void *context_arg, LONG num_files, LPSTR *file_names,              LPLONG status){    return SCC_return_not_supported;}/* Like QueryInfo, but fast and for only a single file.  For example, the   development environment might call this quite frequently to keep its   screen display updated.  */SCC_returnSccGetEvents (void *context_arg, LPSTR file_name,	      LPLONG status,              LPLONG events_remaining){    /* They say this is supposed to only return cached status       information, not go to disk or anything.  I assume that       QueryInfo and probably the usual calls like Get would cause       us to cache the status in the first place.  */    return SCC_return_success;}/* This is where the user gives us the CVSROOT.  */SCC_returnSccGetProjPath (void *context_arg, HWND window, LPSTR user,                LPSTR proj_name, LPSTR local_proj, LPSTR aux_proj,                BOOL allow_change, BOOL *new){    /* For now we just hardcode the CVSROOT.  In the future we will       of course prompt the user for it (simple implementation would       have them supply a string; potentially better implementation       would have menus or something for access methods and so on,       although it might also have a way of bypassing that in case       CVS supports new features that the GUI code doesn't       understand).  We probably will also at some point want a       "project" to encompass both a CVSROOT and a directory or       module name within that CVSROOT, but we don't try to handle       that yet either.  We also will want to be able to use "user"       instead of having the username encoded in the aux_proj or       proj_name, probably.  */    struct context *context = (struct context *)context_arg;    fprintf (context->debuglog, "SccGetProjPath called\n");    /* At least for now we leave the proj_name alone, and just use       the aux_proj.  */    strncpy (proj_name, "zwork", SCC_max_path);    strncpy (aux_proj, ":server:harvey:/home/kingdon/zwork/cvsroot",	     SCC_max_path);    if (local_proj[0] == '\0' && allow_change)	strncpy (local_proj, "d:\\sccwork", SCC_max_path);    /* I don't think I saw anything in the spec about this,       but let's see if it helps.  */    if (_chdir (local_proj) < 0)	fprintf (context->debuglog, "Error in chdir: %s", strerror (errno));    if (*new)	/* It is OK for us to prompt the user for creating a new	   project.  */	/* We will say that the user said to create a new one.  */	*new = 1;    fflush (context->debuglog);    return SCC_return_success;}/* Pretty much similar to SccPopulateList.  */SCC_returnSccAddFromScc (void *context_arg, HWND window, LONG *files,               char ***file_names){    struct context *context = (struct context *)context_arg;    /* For now we have hardcoded the notion that there are two files,       foo.c and bar.c.  */#define NUM_FILES 2    if (files == NULL)    {	char **p;	/* This means to free the memory that is allocated for	   file_names.  */	for (p = *file_names; *p != NULL; ++p)	{	    fprintf (context->debuglog, "Freeing %s\n", *p);	    free (*p);	}    }    else    {	*file_names = malloc ((NUM_FILES + 1) * sizeof (char **));	if (*file_names == NULL)	    return malloc_error (context);	(*file_names)[0] = malloc (80);	if ((*file_names)[0] == NULL)	    return malloc_error (context);	strcpy ((*file_names)[0], "foo.c");	(*file_names)[1] = malloc (80);	if ((*file_names)[1] == NULL)	    return malloc_error (context);	strcpy ((*file_names)[1], "bar.c");	(*file_names)[2] = NULL;	*files = 2;	/* Are we supposed to also Get the files?  Or is the IDE	   next going to call SccGet on each one?  The spec doesn't	   say explicitly.  */    }    fprintf (context->debuglog, "Success in SccAddFromScc\n");    fflush (context->debuglog);    return SCC_return_success;}/* This changes several aspects of how we interact with the IDE.  */SCC_returnSccSetOption (void *context_arg,	      LONG option,	      LONG val){    return SCC_return_success;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -