/* Read Pro-Net BOM file and create Pro-Board Part List                */
/* This is a simple program.  It does not maintain a library of parts.
   You may optionally abort if a Part List already exists.
   It also does a very simple sort of the Device Labels.               */

/* $VER: BOMtoPL V1.0 by Jeff Lindstrom ©1992  EP Systems              */

/* Add the Support Library if not already in the system                */
IF ~SHOW('L', 'rexxsupport.library') THEN
  CALL ADDLIB('rexxsupport.library',0,-30)

ADDRESS COMMAND

/* ASCII New Line character */
NL = '0A'x

BOMdir = "" /* Set BOM directory for use */
IF ARG(1, 'Exists') THEN BOMdir = ARG(1)
                    ELSE IF EXISTS(PNPOST) THEN BOMdir = "PNPOST/"
  
IF BOMdir = "" THEN
DO
  DS = 0  /* BOOLEAN Directory Specification flag  */
  /* Use current directory to list BOM files */
  'LIST >T:BOMFILES #?.BOM NOHEAD QUICK'
END
ELSE /* BOM directory specified.  Check format & verify that it exists */
DO
  DS = 1  /* BOOLEAN Directory Specification flag  */
  /* If no directory or sub-directory marker (':' or '/') is present,
     add a directory marker to end of text.
     If the Post Processing directory PNPOST is a sub-directory of the
     current directory, it will have automatically been entered as the 
     working directory with the sub-directory marker '/' added, if no
     directory was specified on the command line.                      */
  IF (0 = VERIFY(BOMdir, ':/', M)) THEN BOMdir = BOMdir || ':'
  LastChar = (SUBSTR(BOMdir, LENGTH(BOMdir), 1))
  
  /* If the last character is not ':' or '/', add '/' (the ':' would
     already be in the body of the text because of the 3rd line up). */
  IF ((INDEX(':/', LastChar)) = 0) THEN BOMdir = BOMdir || '/'
  IF ~EXISTS(BOMdir) THEN
  DO
    SAY "Directory path doesn't exist."
    EXIT
  END
  
  /* By default, use the PNPOST sub-directory of the specified directory
     if it exists (this is Pro-Net's default action, anyway).     */
  IF EXISTS(BOMdir'PNPOST') THEN BOMdir = BOMdir || 'PNPOST/'
  
  'LIST >T:BOMFILES 'BOMdir'#?.BOM NOHEAD QUICK'
END

PARSE VALUE STATEF('T:BOMFILES') WITH Type Size Other
IF Size = 0 THEN
DO
  SAY NL "No .BOM files in this directory." NL
  EXIT
END

'SORT T:BOMFILES T:BOMFILES'
IF DS THEN SAY NL"Bills of Materials in" BOMdir
      ELSE SAY NL"Bills of Materials"
'TYPE T:BOMFILES'
'DELETE >NIL: T:BOMFILES'
OPTIONS PROMPT NL "Enter the Bill Of Materials (no suffix): "
PULL BOM

IF BOM = "" THEN
DO
  SAY NL "No BOM file specified." NL
  EXIT
END

Check = 1
IF DS THEN
 DO
  IF EXISTS(BOMdir || BOM".BOM") THEN Check = 0
 END
ELSE
  IF EXISTS(BOM".BOM") THEN Check = 0

IF Check THEN
DO
  SAY "Bill of Materials" BOM".BOM does not exist.  Check the list."
  EXIT
END

/* Check if Part List already exists */
Check = 0
IF DS THEN
 DO
  IF EXISTS(BOMdir || BOM'.PAT') THEN Check = 1
 END
ELSE IF EXISTS(BOM'.PAT') THEN Check = 1

IF Check THEN
DO
  SAY NL "A Part List named" BOM".PAT already exists."
  SAY " The information in this file will not be used."
  OPTIONS PROMPT NL "Do you wish to continue? (Y/N)=> "
  PULL Choice
  IF (SUBSTR(Choice, 1, 1) ~= 'Y') THEN EXIT
  SAY NL "Say bye-bye to the old Part List." NL
END

IF DS THEN CALL OPEN('BOMlist', BOMdir || BOM'.BOM', 'r')
      ELSE CALL OPEN('BOMlist', BOM'.BOM', 'r')

/* Open temporary Part List (no header information) */
CALL OPEN('PATlist', 'T:PARTS', 'w')

/* Throw away first 8 lines from the Bill of Materials */
DO 9
  BOMline = READLN('BOMlist')
END

/* Read lines from BOM & prompt for Device Type */
DO UNTIL LENGTH(BOMline) = 0

  /* Device Names can have included spaces, so do not use PARSE */
  Device = STRIP(SUBSTR(BOMline, 1, 15))
  
  /* Adjust BOMline to eliminate Device Name from text string   */
  BOMline = SUBSTR(BOMline, 16)
  PARSE VALUE BOMline WITH Quantity Labels
  
  /* Labels can continue on next line, so put all Labels in one string */
  /* The last Label is denoted by a semi-colon                         */
  DO WHILE (0 = INDEX(Labels, ";"))
    BOMline = READLN('BOMlist')
    Labels = Labels || BOMline
  END
  
  /* Get rid of all spaces in Labels string and the ";" at end of string */
  Labels = COMPRESS(STRIP(Labels,, ";"))
  
  /* Get Device type */
  OPTIONS PROMPT NL "Is the" Device" a <D>IP, <S>IP, <T>wo-Pin, or <L>ib? "
  PULL description
  Type = SUBSTR(description, 1, 1)
  DO WHILE (INDEX("DSTLE", Type) = 0)
    SAY "Try again: Is the" Device" a <D>IP, <S>IP, <T>wo-Pin, or <L>ib?"
    OPTIONS PROMPT "(<E>scape) => "
    PULL description
    Type = SUBSTR(description, 1, 1)
    IF Type = 'E' THEN EXIT
  END
  
  SELECT
    WHEN Type = 'D' THEN
     DO
      OPTIONS PROMPT " How many pins does this DIP have? "
      PULL Number
      DO FOREVER
        IF (Number//2 = 0) THEN LEAVE /* Modulo 2 check for evenness */
        SAY NL "Come on! DIPs don't have an odd number of Pins."
        PULL Number
      END
      OPTIONS PROMPT " What is the separation between rows of Pins? "
      PULL Separation
      /* I was going to automatically convert mils to inches,   */
      /* but that would make it difficult for Metric unit users */
      /* To use, eliminate the comments around the next line.   */
      /* IF Number > 2 THEN Number = Number/1000                */
      
      /* Write the data */
      LabelInfo = '/' || Type || '/' || Number || '/' || Separation || ';'
      CALL WriteLine()
     END
    
    WHEN Type = 'S' THEN
     DO
      OPTIONS PROMPT " How many pins does this SIP have? "
      PULL Number
      
      LabelInfo = '/' || Type || '/' || Number || ';'
      CALL WriteLine()
     END
    
    WHEN Type = 'T' THEN
     DO
      OPTIONS PROMPT " What is the pin separation? "
      PULL Separation
      
      LabelInfo = '/' || Type || '/' || Separation || ';'
      CALL WriteLine()
     END
    
    WHEN Type = 'L' THEN
     DO
      OPTIONS PROMPT " Which Library Part do you want to use here? "
      PARSE PULL Library   /* Don't convert to upper case */
      
      LabelInfo = '/' || Type || '/' || Library || ';'
      CALL WriteLine()
     END
  END
  
  /* Get next line of data for the next loop */
  BOMline = READLN('BOMlist')

END

CALL CLOSE('PATlist')
CALL CLOSE('BOMlist')
CALL OPEN('HText', 'T:HEADER', 'w')
CALL WRITELN('HText', "")
CALL WRITELN('HText', "Part List :")
CALL WRITELN('HText', "")
CALL CLOSE('HText')

'SORT T:PARTS T:PARTS'

IF DS THEN 'JOIN T:HEADER T:PARTS AS 'BOMdir || BOM'.PAT'
      ELSE 'JOIN T:HEADER T:PARTS AS 'BOM'.PAT'

'DELETE >NIL: T:PARTS'
'DELETE >NIL: T:HEADER'

SAY NL "  New Part List written." NL
EXIT

/* Extract individual Device Labels from the string Labels */
/* and write each line of data to the Part List file.      */

WriteLine:

Labels = STRIP(Labels,, NL)
PARSE VAR Labels Label','Labels

DO UNTIL (LENGTH(Label) = 0)
  CALL WRITELN('PATlist', Label || LabelInfo)
  PARSE VAR Labels Label','Labels
END

RETURN