565 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
		
		
			
		
	
	
			565 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
|  | /* Copyright (C) The libssh2 project and its contributors.
 | ||
|  |  * | ||
|  |  * SPDX-License-Identifier: BSD-3-Clause | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <string.h>
 | ||
|  | #include <ctype.h>
 | ||
|  | #include <errno.h>
 | ||
|  | 
 | ||
|  | #include <starlet.h>
 | ||
|  | #include <lib$routines.h>
 | ||
|  | #include <ssdef.h>
 | ||
|  | #include <descrip.h>
 | ||
|  | #include <rms.h>
 | ||
|  | 
 | ||
|  | typedef struct manl { | ||
|  |     struct manl *next; | ||
|  |     char *filename; | ||
|  | } man, *manPtr; | ||
|  | 
 | ||
|  | typedef struct pf_fabnam { | ||
|  |     struct FAB dfab; | ||
|  |     struct RAB drab; | ||
|  |     struct namldef dnam; | ||
|  |     char   expanded_filename[NAM$C_MAXRSS + 1]; | ||
|  | } pfn, *pfnPtr; | ||
|  | 
 | ||
|  | /*----------------------------------------------------------*/ | ||
|  | 
 | ||
|  | fpcopy(char *output, char *input, int len) | ||
|  | { | ||
|  |     char *is, *os; | ||
|  |     int i; | ||
|  | 
 | ||
|  |     if(len) { | ||
|  |         for(is = input, os = output, i = 0; i < len; ++i, ++is, ++os) { | ||
|  |             *os = *is; | ||
|  |         } | ||
|  |         *os = 0; | ||
|  |     } | ||
|  |     else { | ||
|  |         output[0] = 0; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /*----------------------------------------------------------*/ | ||
|  | /* give part of ilename in partname. See code for proper
 | ||
|  |    value of i ( 0 = node, 1 = dev, 2 = dir, 3 = name etc. | ||
|  | */ | ||
|  | 
 | ||
|  | int fnamepart(char *inputfile, char *part, int whatpart) | ||
|  | { | ||
|  |     pfnPtr pf; | ||
|  |     int    status; | ||
|  |     char   ipart[6][256], *i, *p; | ||
|  | 
 | ||
|  |     pf = calloc(1, sizeof(pfn)); | ||
|  | 
 | ||
|  |     pf->dfab = cc$rms_fab; | ||
|  |     pf->drab = cc$rms_rab; | ||
|  |     pf->dnam = cc$rms_naml; | ||
|  | 
 | ||
|  |     pf->dfab.fab$l_naml = &pf->dnam; | ||
|  | 
 | ||
|  |     pf->dfab.fab$l_fna = (char *) -1; | ||
|  |     pf->dfab.fab$l_dna = (char *) -1; | ||
|  |     pf->dfab.fab$b_fns = 0; | ||
|  |     pf->dfab.fab$w_ifi = 0; | ||
|  | 
 | ||
|  |     pf->dnam.naml$l_long_defname = NULL;  /* inputfile; */ | ||
|  |     pf->dnam.naml$l_long_defname_size = 0; /* strlen(inputfile); */ | ||
|  | 
 | ||
|  |     pf->dnam.naml$l_long_filename = inputfile; | ||
|  |     pf->dnam.naml$l_long_filename_size = strlen(inputfile); | ||
|  | 
 | ||
|  |     pf->dnam.naml$l_long_expand = pf->expanded_filename; | ||
|  |     pf->dnam.naml$l_long_expand_alloc = NAM$C_MAXRSS; | ||
|  | 
 | ||
|  |     pf->dnam.naml$b_nop |= NAML$M_SYNCHK | NAML$M_PWD; | ||
|  | 
 | ||
|  |     status = sys$parse(&pf->dfab, 0, 0); | ||
|  |     if(!(status&1)) { | ||
|  |         free(pf); | ||
|  |         return status; | ||
|  |     } | ||
|  | 
 | ||
|  |     fpcopy(ipart[0], pf->dnam.naml$l_long_node, | ||
|  |                      pf->dnam.naml$l_long_node_size); | ||
|  |     fpcopy(ipart[1], pf->dnam.naml$l_long_dev, | ||
|  |                      pf->dnam.naml$l_long_dev_size); | ||
|  |     fpcopy(ipart[2], pf->dnam.naml$l_long_dir, | ||
|  |                      pf->dnam.naml$l_long_dir_size); | ||
|  |     fpcopy(ipart[3], pf->dnam.naml$l_long_name, | ||
|  |                      pf->dnam.naml$l_long_name_size); | ||
|  |     fpcopy(ipart[4], pf->dnam.naml$l_long_type, | ||
|  |                      pf->dnam.naml$l_long_type_size); | ||
|  |     fpcopy(ipart[5], pf->dnam.naml$l_long_ver, | ||
|  |                      pf->dnam.naml$l_long_ver_size); | ||
|  | 
 | ||
|  |     for(i = ipart[whatpart], p = part; *i; ++i, ++p) { | ||
|  |         if(p == part) { | ||
|  |             *p = toupper(*i); | ||
|  |         } | ||
|  |         else { | ||
|  |             *p = tolower(*i); | ||
|  |         } | ||
|  |     } | ||
|  |     *p = 0; | ||
|  | 
 | ||
|  |     free(pf); | ||
|  |     return 1; | ||
|  | } | ||
|  | /*----------------------------------------------------------*/ | ||
|  | 
 | ||
|  | int find_file(char *filename, char *gevonden, int *findex) | ||
|  | { | ||
|  |     int     status; | ||
|  |     struct  dsc$descriptor gevondend; | ||
|  |     struct  dsc$descriptor filespec; | ||
|  |     char    gevonden_file[NAM$C_MAXRSS + 1]; | ||
|  | 
 | ||
|  |     filespec.dsc$w_length = strlen(filename); | ||
|  |     filespec.dsc$b_dtype  = DSC$K_DTYPE_T; | ||
|  |     filespec.dsc$b_class  = DSC$K_CLASS_S; | ||
|  |     filespec.dsc$a_pointer = filename; | ||
|  | 
 | ||
|  |     gevondend.dsc$w_length = NAM$C_MAXRSS; | ||
|  |     gevondend.dsc$b_dtype  = DSC$K_DTYPE_T; | ||
|  |     gevondend.dsc$b_class  = DSC$K_CLASS_S; | ||
|  |     gevondend.dsc$a_pointer = gevonden_file; | ||
|  | 
 | ||
|  |     status = lib$find_file(&filespec, &gevondend, findex, 0, 0, 0, 0); | ||
|  | 
 | ||
|  |     if((status & 1) == 1) { | ||
|  |         /* !checksrc! disable BANNEDFUNC 1 */ /* FIXME */ | ||
|  |         strcpy(gevonden, strtok(gevonden_file, " ")); | ||
|  |     } | ||
|  |     else { | ||
|  |          gevonden[0] = 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | 
 | ||
|  | manPtr addman(manPtr *manroot, char *filename) | ||
|  | { | ||
|  |     manPtr m, f; | ||
|  | 
 | ||
|  |     m = calloc(1, sizeof(man)); | ||
|  |     if(!m) | ||
|  |         return NULL; | ||
|  | 
 | ||
|  |     m->filename = strdup(filename); | ||
|  | 
 | ||
|  |     if(!*manroot) { | ||
|  |         *manroot = m; | ||
|  |     } | ||
|  |     else { | ||
|  |         for(f = *manroot; f->next; f = f->next) | ||
|  |             ; | ||
|  |         f->next = m; | ||
|  |     } | ||
|  |     return m; | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | void freeman(manPtr *manroot) | ||
|  | { | ||
|  |     manPtr m, n; | ||
|  | 
 | ||
|  |     for(m = *manroot; m; m = n) { | ||
|  |         free(m->filename); | ||
|  |         n = m->next; | ||
|  |         free(m); | ||
|  |     } | ||
|  |     *manroot = NULL; | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | 
 | ||
|  | int listofmans(char *filespec, manPtr *manroot) | ||
|  | { | ||
|  |     manPtr  r; | ||
|  |     int     status; | ||
|  |     int     ffindex = 0; | ||
|  |     char    gevonden[NAM$C_MAXRSS + 1]; | ||
|  | 
 | ||
|  |     for(;;) { | ||
|  |         status = find_file(filespec, gevonden, &ffindex); | ||
|  | 
 | ||
|  |         if((status&1)) { | ||
|  |             r = addman(manroot, gevonden); | ||
|  |             if(!r) | ||
|  |                 return 2; | ||
|  |         } | ||
|  |         else { | ||
|  |             if(!(status&1)) | ||
|  |                 break; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     lib$find_file_end(&ffindex); | ||
|  |     if(status == RMS$_NMF) | ||
|  |         status = 1; | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | 
 | ||
|  | int convertman(char *filespec, FILE *hlp, int base_level, int add_parentheses) | ||
|  | { | ||
|  |     FILE    *man; | ||
|  |     char    *in, *uit; | ||
|  |     char    *m, *h; | ||
|  |     size_t  len, thislen, maxlen = 50000; | ||
|  |     int     bol, mode, return_status = 1; | ||
|  |     char subjectname[NAM$C_MAXRSS + 1]; | ||
|  | 
 | ||
|  |     in  = calloc(1, maxlen + 1); | ||
|  |     uit = calloc(1, maxlen + 1); | ||
|  | 
 | ||
|  |     if(!in || !uit) | ||
|  |         return 2; | ||
|  | 
 | ||
|  |     man = fopen(filespec, "r"); | ||
|  |     if(!man) | ||
|  |         return vaxc$errno; | ||
|  | 
 | ||
|  |     for(len = 0; !feof(man) && len < maxlen; len += thislen) { | ||
|  |         thislen = fread(in + len, 1, maxlen - len, man); | ||
|  |     } | ||
|  | 
 | ||
|  |     fclose(man); | ||
|  | 
 | ||
|  |     m = in; | ||
|  |     h = uit; | ||
|  | 
 | ||
|  |     *(m + len) = 0; | ||
|  | 
 | ||
|  |     for(mode = 0, bol = 1; *m; ++m) { | ||
|  | 
 | ||
|  |         switch(mode) { | ||
|  |         case 0: | ||
|  |             switch(*m) { | ||
|  |             case '.': | ||
|  |                 if(bol) { | ||
|  |                     mode = 1; | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     *h = *m; | ||
|  |                     ++h; | ||
|  |                 } | ||
|  |                 break; | ||
|  |             case '\\': | ||
|  |                 if(bol) { | ||
|  |                     *h = ' '; ++h; | ||
|  |                     *h = ' '; ++h; | ||
|  |                 } | ||
|  |                 mode = 2; | ||
|  |                 break; | ||
|  |             default: | ||
|  |                 if(bol) { | ||
|  |                     *h = ' '; ++h; | ||
|  |                     *h = ' '; ++h; | ||
|  |                 } | ||
|  |                 *h = *m; | ||
|  |                 ++h; | ||
|  |                 break; | ||
|  |             } | ||
|  |             break; | ||
|  | 
 | ||
|  |         case 1: /* after . at bol */ | ||
|  |             switch(*m) { | ||
|  |             case '\\': | ||
|  |                 while(*m != '\n' && *m != '\r' && *m) | ||
|  |                     ++m; | ||
|  |                 mode = 0; | ||
|  |                 break; | ||
|  |             case 'B': | ||
|  |                 ++m; | ||
|  |                 *h = ' '; ++h; | ||
|  |                 mode = 0; | ||
|  |                 break; | ||
|  |             case 'I': | ||
|  |                 /* remove preceding eol */ | ||
|  |                 if(*(m + 1) != 'P') { | ||
|  |                     --h; | ||
|  |                     while((*h == '\n' || *h == '\r') && h > uit) | ||
|  |                         --h; | ||
|  |                     ++h; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 /* skip .Ix */ | ||
|  |                 for(; *m != ' ' && *m != '\n' && *m != '\r'; ++m) | ||
|  |                     ; | ||
|  | 
 | ||
|  |                 /* copy line up to EOL */ | ||
|  | 
 | ||
|  |                 for(; *m != '\n' && *m != '\r' && *m; ++m, ++h) | ||
|  |                     *h = *m; | ||
|  | 
 | ||
|  |                 /* if line ends in ., this is an EOL */ | ||
|  | 
 | ||
|  |                 if(*(h-1) == '.') { | ||
|  |                     --h; | ||
|  |                     --m; | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     /* if line does not end in ., skip EOL in source */ | ||
|  | 
 | ||
|  |                     if(*(m + 1) == '\n' || *(m + 1) == '\r') | ||
|  |                         ++m; | ||
|  |                 } | ||
|  |                 mode = 0; | ||
|  |                 break; | ||
|  |             case 'S': | ||
|  |                 if(*(m + 1) == 'H') { | ||
|  |                     *h = '\n';++h; | ||
|  |                     if(strncmp(m + 3, "NAME", 4) == 0 || | ||
|  |                        strncmp(m + 3, "SYNOPSIS", 8) == 0 || | ||
|  |                        strncmp(m + 3, "DESCRIPTION", 11) == 0) { | ||
|  |                         while(*m != '\n' && *m != '\r') | ||
|  |                             ++m; | ||
|  |                         mode = 0; | ||
|  |                     } | ||
|  |                     else { | ||
|  |                         ++m; | ||
|  | 
 | ||
|  |                         /* write help level, and flag it */ | ||
|  | 
 | ||
|  |                         *h = '0' + base_level + 1; ++h; | ||
|  |                         return_status |= 2; | ||
|  | 
 | ||
|  |                         *h = ' '; ++h; | ||
|  | 
 | ||
|  |                         /* skip H (or whatever after S) and blank */ | ||
|  |                         ++m; ++m; | ||
|  | 
 | ||
|  |                         for(; *m != '\n' && *m != '\r' && *m; ++m, ++h) { | ||
|  | 
 | ||
|  |                            /* write help label in lowercase, skip quotes */ | ||
|  |                            /* fill blanks with underscores */ | ||
|  | 
 | ||
|  |                            if(*m != '\"') { | ||
|  |                                *h = tolower(*m); | ||
|  |                                if(*h == ' ') | ||
|  |                                    *h = '_'; | ||
|  |                            } | ||
|  |                            else { | ||
|  |                                --h; | ||
|  |                            } | ||
|  |                         } | ||
|  | 
 | ||
|  |                         /* Add a linefeed or two */ | ||
|  | 
 | ||
|  |                         *h = *m; ++h; | ||
|  |                         *h = *m; ++h; | ||
|  | 
 | ||
|  |                         mode = 0; | ||
|  |                     } | ||
|  |                 } | ||
|  |                 break; | ||
|  |             case 'T': | ||
|  |                 if(*(m + 1) == 'H') { | ||
|  |                     *h = '0' + base_level; ++h; | ||
|  |                     return_status |= 2; | ||
|  |                     *h = ' '; ++h; | ||
|  |                     for(m = m + 3; *m != ' ' && *m; ++m, ++h) { | ||
|  |                         *h = *m; | ||
|  |                     } | ||
|  |                     if(add_parentheses) { | ||
|  |                         *h = '('; ++h; | ||
|  |                         *h = ')'; ++h; | ||
|  |                     } | ||
|  |                     while(*m != '\n' && *m != '\r' && *m) | ||
|  |                         ++m; | ||
|  |                     mode = 0; | ||
|  |                 } | ||
|  |                 break; | ||
|  |             default: | ||
|  |                 ++m; | ||
|  |                 mode = 0; | ||
|  |                 break; | ||
|  |             } | ||
|  |             break; | ||
|  |         case 2: /* after \ skip two characters or print the backslash */ | ||
|  |             switch(*m) { | ||
|  |                 case '\\': | ||
|  |                     *h = *m; | ||
|  |                     ++h; | ||
|  |                     mode = 0; | ||
|  |                     break; | ||
|  |                 default: | ||
|  |                     ++m; | ||
|  |                     mode = 0; | ||
|  |                     break; | ||
|  |             } | ||
|  |             break; | ||
|  |         } /* end switch mode */ | ||
|  | 
 | ||
|  |         bol = 0; | ||
|  |         if(*m == '\n' || *m == '\r') | ||
|  |             bol = 1; | ||
|  | 
 | ||
|  |     } /* end for mode */ | ||
|  | 
 | ||
|  |     *h = 0; | ||
|  | 
 | ||
|  | 
 | ||
|  |     if(return_status & 2) { | ||
|  |         fprintf(hlp, "%s\n\n", uit); | ||
|  |     } | ||
|  |     else { | ||
|  |         fnamepart(filespec, subjectname, 3); | ||
|  |         if(*subjectname) { | ||
|  |             fprintf(hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); | ||
|  |         } | ||
|  |         else { | ||
|  |             /* No filename (as is the case with a logical),
 | ||
|  |                use first word as subject name */ | ||
|  |             char *n, *s; | ||
|  | 
 | ||
|  |             for(n = in; isspace(*n); ++n) | ||
|  |                 ; | ||
|  |             for(s = subjectname; !(isspace(*n)); ++n, ++s) | ||
|  |                 *s = *n; | ||
|  |             *s = 0; | ||
|  | 
 | ||
|  |             fprintf(hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /*
 | ||
|  |      printf("read %d from %s, written %d to helpfile, return_status = %d\n", | ||
|  |         len, filespec, strlen(uit), return_status); | ||
|  |     */ | ||
|  | 
 | ||
|  |     free(m); | ||
|  |     free(h); | ||
|  | 
 | ||
|  |     return 1; | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | 
 | ||
|  | int convertmans(char *filespec, char *hlpfilename, int base_level, int append, | ||
|  |                 int add_parentheses) | ||
|  | { | ||
|  |     int status = 1; | ||
|  |     manPtr  manroot = NULL, m; | ||
|  |     FILE    *hlp; | ||
|  | 
 | ||
|  |     if(append) { | ||
|  |         hlp = fopen(hlpfilename, "a+"); | ||
|  |     } | ||
|  |     else { | ||
|  |         hlp = fopen(hlpfilename, "w"); | ||
|  |     } | ||
|  | 
 | ||
|  |     if(!hlp) | ||
|  |         return vaxc$errno; | ||
|  | 
 | ||
|  |     status = listofmans(filespec, &manroot); | ||
|  |     if(!(status&1)) | ||
|  |         return status; | ||
|  | 
 | ||
|  |     for(m = manroot; m; m = m->next) { | ||
|  |         status = convertman(m->filename, hlp, base_level, add_parentheses); | ||
|  |         if(!(status&1)) { | ||
|  |             fprintf(stderr, "Convertman of %s went wrong\n", m->filename); | ||
|  |             break; | ||
|  |         } | ||
|  |     } | ||
|  |     freeman(&manroot); | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------*/ | ||
|  | void print_help(void) | ||
|  | { | ||
|  |     fprintf(stderr, | ||
|  |         "Usage: [-a] [-b x] convertman <manfilespec> <helptextfile>\n" | ||
|  |         "       -a append <manfilespec> to <helptextfile>\n" | ||
|  |         "       -b <baselevel> if no headers found create one " | ||
|  |                    "with level <baselevel>\n" | ||
|  |         "          and the filename as title.\n" | ||
|  |         "       -p add parentheses() to baselevel help items.\n"); | ||
|  | } | ||
|  | /*--------------------------------------------*/ | ||
|  | 
 | ||
|  | main(int argc, char **argv) | ||
|  | { | ||
|  |     int     status; | ||
|  |     int     i, j; | ||
|  |     int     append, base_level, basechange, add_parentheses; | ||
|  |     char    *manfile = NULL; | ||
|  |     char    *helpfile = NULL; | ||
|  | 
 | ||
|  |     if(argc < 3) { | ||
|  |         print_help(); | ||
|  |         return 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     append     = 0; | ||
|  |     base_level = 1; | ||
|  |     basechange = 0; | ||
|  |     add_parentheses = 0; | ||
|  | 
 | ||
|  |     for(i = 1; i < argc; ++i) { | ||
|  |         if(argv[i][0] == '-') { | ||
|  |             for(j = 1; argv[i][j]; ++j) { | ||
|  |                 switch(argv[i][j]) { | ||
|  |                     case 'a': | ||
|  |                         append = 1; | ||
|  |                         break; | ||
|  |                     case 'b': | ||
|  |                         if((i + 1) < argc) { | ||
|  |                             base_level = atoi(argv[i + 1]); | ||
|  |                             basechange = 1; | ||
|  |                         } | ||
|  |                         break; | ||
|  |                     case 'p': | ||
|  |                         add_parentheses = 1; | ||
|  |                         break; | ||
|  |                 } | ||
|  |             } | ||
|  |             if(basechange) { | ||
|  |                 basechange = 0; | ||
|  |                 i = i + 1; | ||
|  |             } | ||
|  |         } | ||
|  |         else { | ||
|  |             if(!manfile) { | ||
|  |                 manfile = strdup(argv[i]); | ||
|  |             } | ||
|  |             else if(!helpfile) { | ||
|  |                 helpfile = strdup(argv[i]); | ||
|  |             } | ||
|  |             else { | ||
|  |                 fprintf(stderr, "Unrecognized parameter : %s\n", argv[i]); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /*
 | ||
|  |     fprintf(stderr,"manfile: %s, helpfile: %s, append: %d, base_level : %d\n", | ||
|  |             manfile, helpfile, append, base_level); | ||
|  |     */ | ||
|  | 
 | ||
|  |     status = convertmans(manfile, helpfile, base_level, append, | ||
|  |                          add_parentheses); | ||
|  | 
 | ||
|  |     free(manfile); | ||
|  |     free(helpfile); | ||
|  | 
 | ||
|  |     return status; | ||
|  | } |