edlists.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /* CHK=0x5A71 */
  2. /*+--------------------------------------------------------------------------
  3. edlists.c - print edit history
  4. a crocko early effort - no apologies
  5. ---------------------------------------------------------------------------*/
  6. /*+:EDITS:*/
  7. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  8. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  9. /*:08-12-1990-01:10-wht@n4hgf-handle no edit note after trigger */
  10. /*:11-07-1989-03:27-wht-attempt to bring up to date in function if not style */
  11. /*:08-11-1986-11:00-WHT-plus before colon in trigger */
  12. /*:08-06-1986-16:30-WHT-creation */
  13. #ifdef MSDOS
  14. #define LINT_ARGS /* for microsoft C */
  15. #endif
  16. #include "stdio.h"
  17. #include "ctype.h"
  18. #ifndef TRUE
  19. #define TRUE 1
  20. #define FALSE 0
  21. #endif
  22. #ifdef M_I86
  23. #define N_SFILES_MAX (128)
  24. #else
  25. #define N_SFILES_MAX (16384) /* max number of files scanned for match */
  26. #endif
  27. #define S_IN_BUF_MAX (256)
  28. #ifdef MSDOS
  29. #define S_FNAME_MAX (65)
  30. #else
  31. #define S_FNAME_MAX (129) /* max size of a file name */
  32. #endif
  33. /* ASCII */
  34. #define TAB (0x09) /* tab character */
  35. #define CR (0x0D) /* carriage return */
  36. #define LF (0x0A) /* line feed */
  37. #define DEFTABWIDTH (4) /* default tab width */
  38. int tabwidth = DEFTABWIDTH; /* tab width (defaulted) */
  39. int iFiles; /* index into argv array (filenames) */
  40. int nFiles; /* number of input files */
  41. int line_number = 0; /* line number in file */
  42. int cbSearch; /* search string length */
  43. int iargv; /* index into argv */
  44. char *eof_if_zero; /* end of file control flag */
  45. int fInEOF; /* TRUE if input file eof reached */
  46. char Files[N_SFILES_MAX][S_FNAME_MAX]; /* filenames */
  47. char inbuf[S_IN_BUF_MAX];
  48. char cmd_fname[S_FNAME_MAX];
  49. FILE *in_fp;
  50. FILE *cmd_fp;
  51. char *argv0;
  52. /*+---------------------------------------------
  53. help_and_return()
  54. print help text and return to caller
  55. ----------------------------------------------*/
  56. help_and_return()
  57. {
  58. fprintf(stderr,"%s : print edit history (trigger =/*+:EDITS:*/)\n",argv0);
  59. fprintf(stderr,"usage: edlists [-a] file1 [ ...]\n",argv0);
  60. fprintf(stderr,"-a list all edit history, otherwise only latest\n");
  61. fprintf(stderr,"switch placement on command line not critical\n");
  62. } /* end of help_and_return() */
  63. /*+---------------------------------------------
  64. help_and_exit()
  65. print help text and exit normally
  66. ----------------------------------------------*/
  67. help_and_exit()
  68. {
  69. help_and_return();
  70. exit(1);
  71. } /* end of help_and_exit() */
  72. /*+-------------------------------------------------------------------------
  73. to_upper() one would think that this was a relatively standard
  74. type of thing, but MSC specifies toupper() to convert to upper
  75. case if not already and Unix says to subtract 'A'-'a' regardless,
  76. so, a stupid little routine here
  77. --------------------------------------------------------------------------*/
  78. char
  79. to_upper(ch)
  80. char ch;
  81. {
  82. if((ch >= 'a') && (ch <= 'z'))
  83. return(ch - 0x20);
  84. else
  85. return(ch);
  86. } /* end of to_upper() */
  87. /*+-------------------------------------------------------------------------
  88. to_lower() ditto comments of previous procedure
  89. --------------------------------------------------------------------------*/
  90. char
  91. to_lower(ch)
  92. char ch;
  93. {
  94. if( (ch >= 'A') && (ch <= 'Z') )
  95. return(ch + 0x20);
  96. else
  97. return(ch);
  98. } /* end of to_lower() */
  99. /*+----------------------------------------------------------------------------
  100. ulcmpb: Upper/Lower [case insensitive] Compare Bytes
  101. Returns -1 if strings are equal, else failing character position
  102. If the second strings terminates with a null and both strings have matched
  103. character for character until that point, then -1 is returned.
  104. NOTE: this is not a test for complete equality of two strings, but allows
  105. discovery of a string as a substring in a larger containing string.
  106. -----------------------------------------------------------------------------*/
  107. ulcmpb(str1,str2)
  108. char *str1; /* the two strings (terminated with nulls) */
  109. char *str2;
  110. {
  111. register int istr;
  112. for( istr=0 ; ; ++istr )
  113. {
  114. if(str2[istr] == '\0') /* if second string exhausts, match! */
  115. return(-1);
  116. if( ( str1[istr] == '\0' )
  117. || ( to_upper(str1[istr]) != to_upper(str2[istr]) )
  118. )
  119. return(istr);
  120. }
  121. } /* end of ulcmpb() */
  122. /*+-------------------------------------------------------------------------
  123. ulindex: Upper/Lower [case insensitive] Index functioni
  124. Returns position of 'str2' in 'str1' if found
  125. If 'str2' is null, then 0 is returned (null matches anything)
  126. Returns -1 if not found
  127. uses 'ulcmpb'
  128. --------------------------------------------------------------------------*/
  129. ulindex(str1,str2)
  130. char *str1; /* the (target) string to search */
  131. char *str2; /* the (comparand) string to search for */
  132. {
  133. register int istr1; /* moving index into str1 */
  134. register char first_str2; /* first character of str2 as upper case */
  135. register char *mstr; /* moving string pointer */
  136. if(*str2 == '\0') /* null string matches anything */
  137. return(0);
  138. istr1=0; /* first char position */
  139. mstr=str1; /* address of string 1 */
  140. for(;;) /* well, maybe forever; hopefully not */
  141. {
  142. if(*mstr == '\0') /* if we exhaust target string, flunk */
  143. return(-1);
  144. first_str2 = to_upper(*str2); /* 1st str2 character as upper case */
  145. /* Can we find either case of first comparand char in target? */
  146. if( to_upper(*mstr) == first_str2 )
  147. {
  148. /* we have a first char match... does rest of string match? */
  149. if(ulcmpb(mstr,str2) == -1) /* if the rest matches, ... */
  150. return(istr1); /* ... return match position */
  151. }
  152. /* we did not match this time... increment istr1, mstr and try again */
  153. ++istr1;
  154. ++mstr;
  155. }
  156. } /* end of ulindex() */
  157. /*+-------------------------------------------------------------------------
  158. bcat(target,source,source_count)
  159. --------------------------------------------------------------------------*/
  160. char *
  161. bcat(target,source,source_count)
  162. char *target;
  163. char *source;
  164. int source_count;
  165. {
  166. register int pos;
  167. register char *msrc = source;
  168. if(source_count == 0)
  169. return(target);
  170. while(source_count-- && *msrc)
  171. *target++ = *msrc++;
  172. *target = 0;
  173. return(target);
  174. } /* end of bcat */
  175. /*+-------------------------------------------------------------------------
  176. print_edit(fname,buffer)
  177. 000000000011111111112222222222333333333...
  178. 012345678901234567890123456789012345678...
  179. :08-06-1986-16:30-wht-add -a switch *| / replaced with | here
  180. roaches input buffer (must be writable)
  181. --------------------------------------------------------------------------*/
  182. void
  183. print_edit(fname,inbuf)
  184. char *fname;
  185. char *inbuf;
  186. {
  187. register int itmp;
  188. char out[128];
  189. char *cptr;
  190. if(inbuf[0] != ':')
  191. return;
  192. if((itmp = ulindex(inbuf,"*/")) >= 0)
  193. {
  194. inbuf[itmp++] = '\n';
  195. inbuf[itmp] = 0;
  196. }
  197. cptr = out;
  198. cptr = bcat(cptr,&inbuf[7],5);
  199. cptr = bcat(cptr,&inbuf[1],6);
  200. cptr = bcat(cptr,&inbuf[12],6);
  201. strcat(cptr,fname);
  202. strcat(cptr,&inbuf[17]);
  203. fputs(out,stdout);
  204. } /* end of print_edit */
  205. /*+-------------------------------------------------------------------------
  206. main program
  207. --------------------------------------------------------------------------*/
  208. main(argc,argv)
  209. int argc;
  210. char **argv;
  211. {
  212. int iSearch; /* index into search strings */
  213. int nSearch; /* number of search strings */
  214. int matchpos; /* ulindex return param */
  215. int fLineNumber = FALSE; /* if TRUE, prefix line number of matching line to output */
  216. int fMatchPos = FALSE; /* if TRUE, print match position */
  217. int itmp;
  218. int all_flag = 0;
  219. int asm_code = 0;
  220. int c_code = 0;
  221. int hash_flag = 0;
  222. char *indicator;
  223. cmd_fname[0]='\0'; /* no aux cmd file name yet */
  224. nFiles=0; /* no search files yet */
  225. argv0 = argv[0];
  226. /* if there are no arguments, give help */
  227. if( argc < 2 )
  228. help_and_exit(); /* and exit program */
  229. /* parse command line */
  230. for( iargv=1; iargv < argc ; ++iargv ) /* walk iargv from 1 to 'argc' */
  231. {
  232. if((itmp=argv[iargv][0]) != '-') /* if not switch argument */
  233. {
  234. if(itmp == '@') /* if @file */
  235. {
  236. cmd_fp=fopen(&argv[iargv][1],"r"); /* read the '@' file contents */
  237. if(cmd_fp == NULL)
  238. {
  239. fprintf(stderr,"Error opening @file %s.\n",&argv[iargv][1]);
  240. exit(1);
  241. }
  242. do
  243. {
  244. inbuf[0]='\0';
  245. eof_if_zero=fgets(inbuf,sizeof(inbuf)-1,cmd_fp); /* read filename */
  246. if(strlen(inbuf) < 2) /* just a newline is empty */
  247. eof_if_zero = NULL; /* simulate eof in such cases */
  248. if(eof_if_zero == NULL) /* if eof or error, ... */
  249. continue;
  250. if(nFiles == N_SFILES_MAX) /* can we use it? */
  251. {
  252. fprintf(stderr,"\nError: Max files (%d) exceeded.\n",
  253. N_SFILES_MAX);
  254. exit(1);
  255. }
  256. itmp=strlen(inbuf); /* strip trailing newline ... */
  257. inbuf[--itmp]='\0'; /* ... from input record */
  258. strncpy(Files[nFiles++],inbuf,S_FNAME_MAX-1);
  259. printf("\nFile to be searched: %s",inbuf);
  260. }/* end of while not @file eof */ while(eof_if_zero != NULL); /* while not @file input eof or error */
  261. fclose(cmd_fp);
  262. fputs("\n",stdout);
  263. continue;
  264. }/* end of if @file */
  265. if(nFiles == N_SFILES_MAX)
  266. {
  267. fprintf(stderr,"...Max files (%d) exceeded.\n",N_SFILES_MAX);
  268. exit(1);
  269. }
  270. strncpy(Files[nFiles++],argv[iargv],S_FNAME_MAX-1);
  271. continue;
  272. } /* end of if not switch arg */
  273. else /* switch argument */
  274. {
  275. switch(to_lower(argv[iargv][1]))
  276. {
  277. case 'a':
  278. all_flag = 1;
  279. break;
  280. default:
  281. fprintf(stderr,"WARNING: unrecognized switch: %s\n",
  282. argv[iargv]);
  283. break;
  284. }
  285. } /* end of else switch arg */
  286. } /* end of walk iargv */
  287. /* if no files, terminate now */
  288. if(nFiles == 0)
  289. {
  290. printf("No files to search. Program terminated.\n");
  291. exit(1);
  292. }
  293. for(iFiles=0 ; iFiles < nFiles ; ++iFiles)
  294. {
  295. fInEOF=FALSE; /* reset eof indicator */
  296. in_fp=fopen(Files[iFiles],"r"); /* open the target file */
  297. if(in_fp == 0) /* if fopen returns 0 file number, error occurred */
  298. {
  299. printf("\nError opening file %d: %s\n",iFiles,Files[iFiles]);
  300. continue; /* next file */
  301. }
  302. line_number = 0;
  303. /************ per file processing goes below here **************/
  304. while(!fInEOF)
  305. {
  306. if( fgets(inbuf,sizeof(inbuf)-1,in_fp) == 0)
  307. {
  308. /*fprintf(stderr,"%s: no EDITS trigger\n",Files[iFiles]);*/
  309. fInEOF = TRUE;
  310. continue;
  311. }
  312. if( (ulindex(inbuf,"EDITS:") >= 0) &&
  313. ((c_code = !strncmp(inbuf,"/*+:",4)) ||
  314. (asm_code = !strncmp(inbuf,"*+:",3)) ||
  315. (hash_flag = !strncmp(inbuf,"#+:",3))))
  316. {
  317. if(c_code)
  318. indicator = "/*:";
  319. else if(asm_code)
  320. indicator = "*:";
  321. else
  322. indicator = "#:";
  323. if(fgets(inbuf,sizeof(inbuf)-1,in_fp) == 0)
  324. {
  325. printf("EOF after EDITS trigger\n");
  326. break;
  327. }
  328. if(strlen(inbuf) > 1)
  329. print_edit(Files[iFiles],&inbuf[(c_code) ? 2 : 1]);
  330. if(all_flag == 0)
  331. break;
  332. while((fgets(inbuf,sizeof(inbuf)-1,in_fp) != 0) &&
  333. (ulindex(inbuf,indicator) == 0) )
  334. {
  335. print_edit(Files[iFiles],&inbuf[(c_code) ? 2 : 1]);
  336. }
  337. break;
  338. }
  339. } /* end of while !fInEOF */
  340. /************ per file processing goes above here **************/
  341. fclose(in_fp); /* close the target file */
  342. continue;
  343. } /* end of for(iFiles=1...nFiles) */
  344. exit(0);
  345. } /* end of main() */
  346. /* end of edlist.c */
  347. /* vi: set tabstop=4 shiftwidth=4: */