home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / labels / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-01-31  |  16.7 KB  |  566 lines

  1. /*                     -- MAIN.C --
  2.  
  3. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  4. @@                                                                           @@
  5. @@                       Mailing List Label Formatter                        @@
  6. @@                                Main Module                                @@
  7. @@                      (C) Copyright 1987 by Joe Chen                       @@
  8. @@                           All Rights Reserved                             @@
  9. @@                                                                           @@
  10. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  11.  
  12. You may freely distribute this software to others.  But there are
  13. few rules you must follow:
  14.  
  15. 1. You don't profit from it.  You may however ask for minimal fees to
  16.    cover shipping and handling.
  17.  
  18. 2. This program is copyrighted, meaning you may not modify or enhance
  19.    this software and market it.  You may make changes to suit your
  20.    local needs.  Any enhancements are welcomed.
  21.  
  22. 3. Please honor the author by not removing or replacing his name from
  23.    the source codes.
  24.  
  25.  
  26. Feel free to contact me if you have any questions.
  27.  
  28.                     Joe Chen
  29.  
  30. ---------------------------------------------------------------------------
  31. Phones at work: (213) 743-5363, (213) 743-5935; at home: (818) 571-5304
  32. University Computing Services, University of Southern California
  33. UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
  34. ARPA: joec@wasat.usc.edu, joec@ecla.usc.edu
  35. ---------------------------------------------------------------------------
  36.  
  37. Program created by Joe Chen - Jul 24, 1987
  38.  
  39. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  40.  
  41. */
  42.  
  43. /* Internal default form: 32x11x3 */
  44.  
  45. #define DEF_FORM "1083"        /* form name here at USC        */
  46.  
  47. #define ISTRING    NULL        /* initial escape sequence    */
  48. #define IFILL    12        /* fill n rows for adjustments    */
  49. #define FOFFS     0        /* form offset (from top)    */
  50. #define POFFS     0        /* page offset (from left)    */
  51.  
  52. #define LWIDTH    32        /* width (in chars) of each label */
  53. #define LHGAP     4        /* horizontal gap (in chars) between labels */
  54. #define LVGAP     1        /* vertical gap (# of lines) between labels */
  55. #define LCROSS     3        /* number of labels accross */
  56. #define LMLINES    11        /* Maximum lines per label  */
  57. #define LOFFSET     4        /* offset (in chars) from left edge */
  58.                 /* of each label */
  59. #define LROWS     0        /* labels per page, 0=don't care*/
  60.  
  61.  
  62. /*****************************************************************************/
  63. #include <stdio.h>
  64.  
  65. #define QUIT        (perror(argv[0]),dsp_usg(argv[0]),exit(-1))
  66. #define FEXT        ".lbl"    /* file extension for form definition file  */
  67. #define GETC(x)        (((ch=getc(x))=='\n')?line_num++,ch:ch);
  68.  
  69. #ifdef BSD
  70. #include <sys/types.h>
  71. #include <sys/dir.h>
  72. #endif BSD
  73.  
  74. char *def_form = DEF_FORM;    /* default label form                */
  75.  
  76. char *def_istring = ISTRING;    /* initial string/escape sequence           */
  77.  
  78. char *l_istring;
  79.  
  80. int l_ifill = IFILL;        /* Initial label fill for manual adjustments*/
  81.  
  82. int l_foffs = FOFFS;        /* form offset (from top)            */
  83. int l_poffs = POFFS;        /* page offset (from left)            */
  84. int l_width = LWIDTH;        /* width of one label (in characters)       */
  85. int l_hgap  = LHGAP;        /* horizontal gap between labels (in chars) */
  86. int l_vgap  = LVGAP;        /* vertical gap between labels (in chars)   */
  87. int l_cross = LCROSS;        /* number of labels across one row          */
  88. int l_mlines= LMLINES;        /* maximum printable lines per label        */
  89. int l_offset= LOFFSET;        /* offset printing of data (in chars)       */
  90. int l_lrows = LROWS;        /* rows of labels per page                  */
  91.  
  92. FILE *infile = stdin, *outfile = stdout;
  93. int line_num = 1;
  94.  
  95. #define T    1
  96. #define F    0
  97.  
  98. extern char *malloc(), *getcwd();
  99. extern char *rev_date;            /* supplied by Makefile            */
  100. extern FILE *yyin;            /* from lex                */
  101.  
  102. char *inpf = NULL, *outf = NULL;    /* pointer to file names            */
  103. char *form = NULL;            /* pointer to form name             */
  104.  
  105. char **fmt_arry;            /* line formatter            */
  106.  
  107. char *version = "1.1";
  108.  
  109. #ifdef UNIX
  110. #ifdef BSD
  111. static char *os_title = "BSD UNIX Version";
  112. #else
  113. #ifdef USG
  114. static char *os_title = "AT&T UNIX Version";
  115. #endif USG
  116. #endif BSD
  117. #endif UNIX
  118.  
  119. #ifdef MSDOS
  120. static char *os_title = "MS-DOS Verson";
  121. #endif MSDOS
  122.  
  123. /****************************************************************************
  124.   dsp_usg() [Private function] - Display a brief usage info
  125.  
  126.   parameters:    name            Name of this program
  127.  
  128.   exit flags:    none
  129. ****************************************************************************/
  130.  
  131. static void dsp_usg(name)
  132.      char *name;
  133. {
  134.   printf("\nUsage: %s [-f <label form>] [<input file> [output file]]\n",
  135.      name);
  136.   printf("   or: %s -h\n", name);
  137. #ifdef BSD
  138.   printf("   or: %s -l\n", name);    /* list predefined forms */
  139. #endif BSD
  140.   printf("\nWhere: <label form>  is defined in %s,\n",FDIR);
  141.   printf("                     or defined by user in the current directory.");
  142.   printf("\n       <input file>  is a text file containing raw labels.\n");
  143.   printf("       <output file> is the formatted label output.\n");
  144.   printf("       -h            displays this help.\n");
  145.   printf("       -l            lists all predefined forms.\n\n");
  146. } /* dsp_usg() */
  147.  
  148. /****************************************************************************
  149.   list_forms() [Private function] - List predefined forms (BSD Unix only)
  150.  
  151.   parameters:    name        program name (for error display purpose)
  152.  
  153.   exit flags:    none
  154. ****************************************************************************/
  155.  
  156. static void list_forms(name)
  157.      char *name;
  158. {
  159. #ifdef UNIX
  160. #ifdef BSD
  161.   DIR *dirp;            /* directory pointer */
  162.   struct direct *dp;        /* pointer to a directory record */
  163.   char *ext_ptr;        /* extension pointer */
  164.   char tmp[MAXNAMLEN+1], ch, *cur_dir;
  165.   int header = F;
  166.   FILE *f;
  167.  
  168.   if ((dirp = opendir(FDIR)) == (DIR *)NULL) {
  169.     fprintf(stderr,"%s: Cannot Open Directory: %s\n",name, FDIR);
  170.     return;
  171.   }
  172.  
  173.   if ((cur_dir = getcwd(NULL, 100)) == (char *)NULL) {
  174.     fprintf(stderr,"FATAL ERROR: Insufficient Memory\n");
  175.     exit(-1);
  176.   }
  177.   chdir(FDIR);        /* change to directory containing the form defs */
  178.  
  179.   for (dp = readdir(dirp); dp != (struct direct *)NULL; dp = readdir(dirp)) {
  180.     if (strlen(dp->d_name) <= strlen(FEXT))
  181.       continue;
  182.     ext_ptr = &dp->d_name[strlen(dp->d_name)-strlen(FEXT)];
  183.     if (!strcmp(ext_ptr, FEXT)) {    /* must have the same extension */
  184.       (void) strcpy(tmp, dp->d_name);
  185.       /* ignore extension */
  186.       tmp[strlen(tmp)-strlen(FEXT)] = '\0';
  187.       if (!header) {
  188.     fprintf(stderr,"Preset Forms\tRemarks\n");
  189.     fprintf(stderr,"------------\t-------\n");
  190.     header = T;
  191.       }
  192.       /* print out the name of the form */
  193.       fprintf(stderr,"%s\t\t", tmp);
  194.  
  195.       if ((f=fopen(dp->d_name,"r")) == (FILE *)NULL)
  196.     fprintf(stderr,"(Form Unreadable)\n");
  197.       else {
  198.     /* Display the first line, if it is a remark */
  199.     if (getc(f) != '#')
  200.       fprintf(stderr,"(No Remark)\n");
  201.     else {
  202.       while ((ch=getc(f)) == ' ');        /* skip leading spaces */
  203.       ungetc(ch, f);
  204.       while ((ch=getc(f)) != '\n') {
  205.         putc(ch, stderr);            /* print comment       */
  206.         if (feof(f))
  207.           break;
  208.       } /* keep reading info */
  209.       fprintf(stderr,"\n");
  210.     } /* display a line of info */
  211.     fclose(f);
  212.       } /* query file */
  213.     }
  214.   } /* for all entries */
  215.   chdir(cur_dir);        /* change back the directory */
  216.   free(cur_dir);
  217. #endif BSD
  218.  
  219. #ifdef USG
  220.   /* System V listing: for now, just use ls */
  221.   char cmd[100];
  222.   (void) sprintf(cmd, "/bin/ls %s/*%s", FDIR, FEXT);
  223.   (void) system(cmd);
  224. #endif USG
  225. #endif UNIX
  226.  
  227. #ifdef MSDOS
  228.   fprintf(stderr,"Not implemented at this time for MSDOS\n");
  229. #endif MSDOS
  230. } /* list_forms() */
  231.  
  232. /****************************************************************************
  233.   get_record() [Private function] - Reads one label info into internal buffer
  234.  
  235.   parameters:    rec        Buffer for holding one label record
  236.  
  237.   exit flags:    0        end-of-file or no label between periods
  238.         >0        number of lines read for this label
  239. ****************************************************************************/
  240.  
  241. static int get_record(rec)
  242.      char **rec;
  243. {
  244.   char ch, *p;
  245.   int i = 0, j;
  246.  
  247.   do {
  248.     p = rec[i];        /* next line */
  249.     /* read in one line */
  250.     for (j = 0, p[j] = '\0'; ; j++) {
  251.       if (!feof(infile)) {
  252.     if (j > (l_width-l_offset)) {        /* line too long */
  253.       fprintf(stderr,"Line %d: Line too long (%d) - Truncated\n",
  254.           line_num, l_width);
  255.       p[l_width-l_offset] = '\0';        /* force termination */
  256.       while (getc(infile) != '\n')
  257.         if (feof(infile))
  258.           return i;
  259.       line_num++;
  260.       break;
  261.     } /* line too long */
  262.  
  263.     if ((p[j]=getc(infile)) == '\n') {    /* read in next char */
  264.       line_num++;
  265.       p[j] = '\0';
  266.       break;
  267.     } /* if end-of-line, go read next line */
  268.  
  269.     if ((!j)&&(p[j]=='.')) {        /* end of label */
  270.       while (getc(infile) != '\n')
  271.         if (feof(infile))
  272.           break;                /* end of file */
  273.       line_num++;
  274.       return i;                /* return lines read */
  275.     } /* end of label detected */
  276.       }
  277.       else
  278.     return i;
  279.     } /* for */
  280.   } while (++i < l_mlines);    
  281.  
  282.   if ((ch=getc(infile)) != '.')
  283.     fprintf(stderr,"Line %d: Lines Exceeded Limit (%d) - Ignoring the Rest\n",
  284.         line_num,l_mlines);
  285.   ungetc(ch, infile);
  286.  
  287.   /* truncating... */
  288.   while (1) {
  289.     if (getc(infile) == '.') {    /* at the end already */
  290.       while(getc(infile) != '\n')
  291.     if (feof(infile))
  292.       break;
  293.       line_num++;
  294.       return i;
  295.     } /* skip to next label */
  296.     while(getc(infile) != '\n')
  297.       if (feof(infile))
  298.     return i;
  299.     line_num++;
  300.   }
  301. } /* get_record() */
  302.  
  303. /****************************************************************************
  304.   main() [Public function] - Startup routine
  305.  
  306.   parameters:    argc        Number of command-line arguments
  307.         argv        argument array
  308.  
  309.   exit flags:    0        Program terminate normally
  310.         <>0        Error (of some sort) occurred, program aborted
  311. ****************************************************************************/
  312.  
  313. main(argc, argv)
  314.      int argc;
  315.      char **argv;
  316. {
  317.   char **row, **rec, *p, *tmpbuf;
  318.   int arg_limit = 3;    /* argument handler (too hard to explain) */
  319.   register i, j, k, l;
  320.   int cur_col, lines, started = F, row_count;
  321.   FILE *ffile;            /* to read form file */
  322.  
  323.   l_istring = def_istring;
  324.  
  325.   if (argc > 1) {
  326.     /* get brief usage */
  327.     if ((!strcmp(argv[1], "help"))||(!strcmp(argv[1], "-h"))) {
  328.       dsp_usg(argv[0]);
  329.       exit(0);
  330.     }
  331.  
  332.     /* list defined forms in FDIR */
  333.     if (!strcmp(argv[1], "-l")) {
  334.       list_forms(argv[0]);
  335.       exit(0);
  336.     }
  337.   } /* check for single argument */
  338.  
  339.   fprintf(stderr,
  340.       "LABELS: Label/Mailing List Formatter - %s\n", os_title);
  341.   fprintf(stderr,"Release %s - Compiled %s\n\n", version, rev_date);
  342.  
  343.   form = def_form;
  344.  
  345.  
  346.   /* allocate space to hold data format for each line */
  347.   if ((fmt_arry = (char **) malloc(l_mlines*sizeof(char *))) ==(char **)NULL)
  348.     QUIT;
  349.   for (i=l_mlines; i ; i--) {
  350.     fmt_arry[i-1] = malloc(l_width+1);
  351.     if (fmt_arry[i-1] == (char *)NULL)
  352.       QUIT;
  353.     (void) strcpy(fmt_arry[i-1], "%s");    /* default format, data only */
  354.   }
  355.  
  356.   if (argc < 2)
  357.     goto ckarg;
  358.  
  359.   /* Check if user specified his/her own form */
  360.   if (!strcmp(argv[1], "-f")) {
  361.     char *frm_name;
  362.  
  363.     if (argc == 2) {
  364.       fprintf(stderr,"%s: Form name is missing!\n",argv[0]);
  365.       exit(-1);
  366.     }
  367.  
  368.     /* Make a complete file name for form */;
  369.     frm_name = malloc(strlen(FDIR)+strlen(argv[2]+strlen(FEXT)+2));
  370.     if (frm_name == (char *)NULL)
  371.       QUIT;
  372.     arg_limit += 2;
  373.  
  374.     form = argv[2];
  375.  
  376.     /* create a path to open the label form file */
  377.     (void) strcpy(frm_name, FDIR);
  378. #ifdef MSDOS
  379.     (void) strcat(frm_name, "\\");
  380. #else
  381.     (void) strcat(frm_name, "/");
  382. #endif MSDOS
  383.     (void) strcat(frm_name, form);
  384.     (void) strcat(frm_name, FEXT);    /* form extension */
  385.  
  386.     /* open file */
  387.     if ((ffile=fopen(frm_name, "r")) == (FILE *)NULL) {
  388.       /* trouble opening file from library directory, try current directory */
  389.       (void) strcpy(frm_name, ".");
  390. #ifdef MSDOS
  391.       (void) strcat(frm_name, "\\");
  392. #else
  393.       (void) strcat(frm_name, "/");
  394. #endif MSDOS
  395.       (void) strcat(frm_name, form);
  396.       (void) strcat(frm_name, FEXT);    /* form extension */
  397.       if ((ffile=fopen(frm_name, "r")) == (FILE *)NULL) {
  398.     /* cannot open file in current directory either, give up */
  399.     fprintf(stderr,"%s: Cannot read form: %s\n",*argv,form);
  400.     exit(-1);
  401.       }
  402.     } /* open form */
  403.  
  404.     yyin = ffile;
  405.  
  406.     /* now parse the file */
  407.     if (yyparse()) {
  408.       fprintf(stderr,"%s: Error reading form: %s\n",*argv,form);
  409.       exit(-1);
  410.     }
  411.     free(frm_name);
  412.   } /* reading form definitions */
  413.  
  414.  ckarg:
  415.   /* Check if there are too many arguments */
  416.   if (argc > arg_limit) {
  417.     fprintf(stderr,"%s: Too many arguments\n", argv[0]);
  418.     exit(-1);
  419.   }
  420.  
  421.   /* Check if output file is given (has to be the last argument) */
  422.   if (argc > arg_limit-1) {
  423.     if ((outfile = fopen(argv[arg_limit-1], "w")) == (FILE *)NULL)
  424.       QUIT;
  425.     outf = argv[arg_limit-1];
  426.   }
  427.  
  428.   /* Check if input file is given (second to the last argument) */
  429.   if (argc > arg_limit-2) {
  430.     if ((infile = fopen(argv[arg_limit-2],"r")) == (FILE *)NULL)
  431.       QUIT;
  432.     inpf = argv[arg_limit-2];
  433.   }
  434.  
  435.   /* allocate space to hold a row of labels of n across */
  436.   if ((row = (char **) malloc(l_mlines*sizeof(char *))) == (char **)NULL)
  437.     QUIT;
  438.   for (i=l_mlines; i ; i--) {
  439.     row[i-1] = malloc(l_width*l_cross+l_hgap*(l_cross-1)+100);
  440.     if (row[i-1] == (char *)NULL)
  441.       /* insufficient memory */
  442.       QUIT;
  443.   } /* for */
  444.  
  445.   fprintf(stderr,"[Input: %s, Output: %s, Form: %s]\n",
  446.      (inpf!=(char *)NULL)?inpf:"(stdin)",
  447.      (outf!=(char *)NULL)?outf:"(stdout)", form);
  448.  
  449.   /* allocate space to hold one label of n lines */
  450.   if ((rec = (char **) malloc((l_mlines+1)*sizeof(char *))) == (char **)NULL)
  451.     QUIT;
  452.   for (i=l_mlines+1; i ; i--)        /* buffer space should be big */
  453.     if ((rec[i-1] = malloc(l_width*2)) == (char *)NULL)
  454.       QUIT;
  455.  
  456.   /* for formatting purpose */
  457.   if ((tmpbuf = malloc(l_width*2)) == (char *)NULL)
  458.     QUIT;
  459.  
  460.   row_count = l_lrows + 1;        /* ensure checking for form offset */
  461.  
  462.   /* main loop */
  463.   while(T) {
  464.     /* clear one row of labels*/
  465.     for (i = 0; i <  l_mlines; i++)
  466.       for (j = 0, k = (l_width*l_cross+l_hgap*(l_cross-1)); j < k ; j++)
  467.     row[i][j] = ' ';
  468.  
  469.     for (cur_col=0; cur_col < l_cross; cur_col++) {
  470.  
  471.       while (!(lines=get_record(rec)))    /* get one label from input         */
  472.     if (feof(infile)) {        /* if no lines read, probably eof   */
  473.       if (cur_col)
  474.         goto f;            /* flush output                     */
  475.       goto d;            /* quit                             */
  476.     }
  477.  
  478.       /* Check each input line with format string */
  479.       for (i = 0; i < lines; i++) {
  480.     if (!strcmp(fmt_arry[i], "%s"))
  481.       continue;            /* no need to format, use default   */
  482.  
  483.     (void) strcpy(tmpbuf,rec[i]);
  484.     (void) sprintf(rec[i],fmt_arry[i],tmpbuf);
  485.  
  486.     /* truncate if string too long after formatting */
  487.     if (strlen(rec[i]) > (l_width-l_offset)) {
  488.       rec[i][(l_width-l_offset)] = '\0';
  489.       fprintf(stderr,
  490.           "Line %d: Line too long after formatting (%d) - Truncated\n",
  491.           line_num-lines-1+i, l_width);
  492.     } /* string too long after formatting */
  493.       }
  494.  
  495.       for (i = j = (l_mlines-lines)/2, k = 0; i < (j+lines); i++, k++) {
  496.     p = (char *) ((int)row[i] + cur_col*(l_width+l_hgap) + l_offset);
  497.     for (l = 0; rec[k][l]; l++)
  498.       p[l] = rec[k][l];
  499.       } /* fill n lines for one label */
  500.  
  501.     } /* for one row */
  502.  
  503.   f:
  504.     if (!started) {
  505.       /* Output initial string or escape sequence to printer */
  506.       started = T;
  507.       if (l_istring != (char *)NULL)
  508.     fprintf(outfile, l_istring);
  509.       if (l_ifill) {
  510.     int kk;
  511.     /* fills n rows for manual adjustment purposes */
  512.     for (i = 0; i < l_ifill; row_count++, i++) {
  513.  
  514.       if ((row_count < l_lrows)||(!l_lrows))
  515.         kk = 0;
  516.       else {
  517.         kk = l_foffs;
  518.         row_count = 0;
  519.       }
  520.  
  521.       for (; kk < l_mlines; putc('\n', outfile), kk++) {
  522.         for (j = 0; j < l_cross; j++) {
  523.           for (k = l_poffs; k < l_width; k++)
  524.         putc('#', outfile);        /* fill one line of a label */
  525.           if (j < l_cross-1)
  526.         for (k = 0; k < l_hgap; k++)
  527.           fprintf(outfile," ");        /* make horizontal gaps     */
  528.         } /* for one line in label */
  529.       } /* for one row of label */
  530.       for (k = 0; k < l_vgap; putc('\n', outfile), k++);
  531.     } /* for n rows */
  532.       } /* if need to adjust */
  533.     } /* if initial output */
  534.  
  535.     /* print row to output file */
  536.     if ((row_count < l_lrows)||(!l_lrows))
  537.       i = 0;                /* print entire label */
  538.     else {
  539.       /* if there's a form offset, the first row of labels maybe truncated */
  540.       i = l_foffs;
  541.       row_count = 0;
  542.     }
  543.  
  544.     for (k = (l_width*l_cross+l_hgap*(l_cross-1)); i < l_mlines; i++) {
  545.       /* set an absolute length for output */
  546.       row[i][k] = '\0';
  547.  
  548.       /* if there's a page offset, we better look out */
  549.       fprintf(outfile,"%s\n", &row[i][l_poffs]);
  550.     }
  551.  
  552.     /* fill vertical gap */
  553.     for (i = 0; i < l_vgap; i++)
  554.       putc('\n', outfile);
  555.     row_count++;
  556.   } /* process entire file - while() */
  557.  
  558.  d:
  559.   if (infile != stdin)
  560.     fclose(infile);
  561.   if (outfile != stdout)
  562.     fclose(outfile);
  563.  
  564.   fprintf(stderr,"\n%s: Formatting Complete\n",argv[0]);
  565. } /* main() */
  566.