Annotation of researchv10no/cmd/snocone/osnocone.sc, revision 1.1

1.1     ! root        1:        data("b(op,l,r)")
        !             2:        data("u(op,r)")
        !             3:        data("i_fcall(name,head,tail)")
        !             4:        data("fcall(name,args,l,r)")
        !             5:        data("argexp(exp,next)")
        !             6: 
        !             7:        stack = table()
        !             8:        bconv = table(30)
        !             9:        deflist = table(50)
        !            10:        inctab = table()
        !            11:        stno_tab = table(100)
        !            12: 
        !            13:        # The "binfo" structure contains the information needed to
        !            14:        # map Snocone binary operators into SNOBOL4 binary operators.
        !            15:        # The significance of the fields is as follows:
        !            16:        #
        !            17:        #       out     The corresponding SNOBOL4 operator
        !            18:        #       lp      The operator priority when it's on the left
        !            19:        #               side of a precedence comparison
        !            20:        #       rp      The operator priority when it's on the right
        !            21:        #               side of a precedence comparison.  lp is always
        !            22:        #               equal to rp or rp-1; if equal, the operator is
        !            23:        #               left-associative, otherwise right-associative.
        !            24:        #       slp     Like lp, but for the SNOBOL4 operator
        !            25:        #       srp     Like rp, but for the SNOBOL4 operator
        !            26:        #       fn      Non-null if this operator translates into a
        !            27:        #               call to a built-in function instead of an operator.
        !            28:        data("binfo(out,lp,rp,slp,srp,fn)")
        !            29: 
        !            30:        # Paren isn't really an operator, but precedence comparisons
        !            31:        # work out more easily if bconv has an entry for them.
        !            32:        bconv['('] = par_binfo = binfo('',0)
        !            33: 
        !            34:        bconv['='] = binfo('=',1,2,0,1)
        !            35:        bconv['?'] = binfo('?',2,2,1,1)
        !            36:        bconv['|'] = binfo('|',3,3,2,2)
        !            37:        bconv['||'] = or_binfo = binfo('',4,4,0,0,1)
        !            38:        bconv['&&'] = cat_binfo = binfo(' ',5,5,4,4)
        !            39:        bconv['>'] = binfo('GT',6,6,0,0,1)
        !            40:        bconv['<'] = binfo('LT',6,6,0,0,1)
        !            41:        bconv['>='] = binfo('GE',6,6,0,0,1)
        !            42:        bconv['<='] = binfo('LE',6,6,0,0,1)
        !            43:        bconv['=='] = binfo('EQ',6,6,0,0,1)
        !            44:        bconv['!='] = binfo('NE',6,6,0,0,1)
        !            45:        bconv['::'] = binfo('IDENT',6,6,0,0,1)
        !            46:        bconv[':!:'] = binfo('DIFFER',6,6,0,0,1)
        !            47:        bconv[':>:'] = binfo('LGT',6,6,0,0,1)
        !            48:        bconv[':<:'] = binfo('LLT',6,6,0,0,1)
        !            49:        bconv[':>=:'] = binfo('LGE',6,6,0,0,1)
        !            50:        bconv[':<=:'] = binfo('LLE',6,6,0,0,1)
        !            51:        bconv[':==:'] = binfo('LEQ',6,6,0,0,1)
        !            52:        bconv[':!=:'] = binfo('LNE',6,6,0,0,1)
        !            53:        bconv['+'] = binfo('+',7,7,5,5)
        !            54:        bconv['-'] = binfo('-',7,7,5,5)
        !            55:        bconv['/'] = binfo('/',8,8,7,7)
        !            56:        bconv['*'] = binfo('*',8,8,8,8)
        !            57:        bconv['%'] = binfo('REMDR',8,8,0,0,1)
        !            58:        bconv['^'] = binfo('**',9,10,10,11)
        !            59:        bconv['.'] = binfo('.',10,10,11,11)
        !            60:        bconv['$'] = binfo('$',10,10,11,11)
        !            61: 
        !            62:        ht = char(9)
        !            63:        optblank = nspan(" " && ht)
        !            64:        blank = span(" " && ht)
        !            65:        digits = "0123456789"
        !            66:        letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
        !            67: 
        !            68:        integer = span(digits)
        !            69:        exponent = any("eEdD") && (any("+-") | "") && integer
        !            70:        real = integer && "." && (integer | "") && (exponent | "") |
        !            71:                integer && exponent | "." && integer && (exponent | "")
        !            72:        number = real | integer
        !            73: 
        !            74:        string = any("'" && '"') $ squote && break(*squote) && len(1)
        !            75: 
        !            76:        constant = number | string
        !            77:        identifier = any(letters) && nspan(letters && digits)
        !            78:        unaryop = any("+-*&@~?.$")
        !            79:        binaryop = "==" | "!=" | "<=" | ">=" | "&&" | "||" | ":==:" |
        !            80:                ":!=:" | ":>:" | ":<:" | ":>=" | ":<=:" | "::" | ":!:" | 
        !            81:                any("+-*/<>=^.$?|%")
        !            82: 
        !            83:        fcall = identifier . *mkfcall() && optblank &&
        !            84:                (("(" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            85:                optblank && ")" . *invoke(.endfc)) |
        !            86:                ("[" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            87:                optblank && "]" . *invoke(.endfc) . *invoke(.mkarray)))
        !            88: 
        !            89:        term = optblank && (constant . *push() . *dotck() |
        !            90:                identifier . *push() | "(" && *exp && optblank && ")" | fcall)
        !            91:        operand = term | optblank && unaryop . *push() &&
        !            92:                *operand . *invoke(.unop)
        !            93:        exp = "" . *begexp() && *operand &&
        !            94:                arbno(optblank && binaryop . *push() . *invoke(.mkbinfo) &&
        !            95:                *operand . *invoke(.binop)) && "" . *endexp()
        !            96: 
        !            97:        label = optblank && identifier . lab . *emitlab(lab) && optblank && ":"
        !            98: 
        !            99:        clausend = any("{}") . del | rpos(0)
        !           100: 
        !           101:        clause = fence && arbno(label) && optblank &&
        !           102:                ("if" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !           103:                "while" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !           104:                (kw("return") | kw("freturn") | kw("nreturn")) . cl_type && optblank &&
        !           105:                        ("" . *push() | *exp) &&
        !           106:                        optblank && clausend |
        !           107:                "go" && optblank && "to" && blank &&
        !           108:                        identifier . dest . *invoke(.gocl) |
        !           109:                ("{" | "}") . cl_type |
        !           110:                ("do" | kw("else")) . cl_type && (span(" " && ht) | rpos(0)) |
        !           111:                "procedure" . cl_type && blank && identifier . fname |
        !           112:                "struct" . cl_type && blank && identifier . stname |
        !           113:                "for" . cl_type && optblank &&
        !           114:                        "(" && *exp && optblank && "," && *exp && optblank &&
        !           115:                        "," && *exp && optblank && ")" |
        !           116:                rpos(0) . cl_type && *invoke(.emiteos) |
        !           117:                *exp && optblank && clausend . *invoke(.expcl))
        !           118: 
        !           119:        gl_files = table()
        !           120:        gl_lines = table()
        !           121:        gl_index = -1
        !           122: 
        !           123:        emit_stno = 0
        !           124: 
        !           125:        &stlimit = 1000000000
        !           126: #
        !           127: #      save the current state -- we really begin execution here.
        !           128:        exit(3)
        !           129: #
        !           130: #      Establish a starting point for input files
        !           131:        gl_arg = host(3) - 1
        !           132:        if (~host (2, host(3))) {
        !           133:                output = "snocone: nothing to compile"
        !           134:                go to end
        !           135:        }
        !           136: 
        !           137:        if (~gl_nextfile()) {
        !           138:                go to end
        !           139:        }
        !           140: #
        !           141: #      establish the "object" file
        !           142:        outfile = "a.out"
        !           143:        &errlimit = &errlimit + 1
        !           144:        savexit = setexit()
        !           145:        if (~output(.outf,-1,outfile)) {
        !           146:                output = "cannot write " && outfile
        !           147:                go to end
        !           148:        }
        !           149:        &errlimit = &errlimit - 1
        !           150:        setexit (savexit)
        !           151: 
        !           152:        outf = "#!/usr/bin/spitbol -s16k"
        !           153: #
        !           154: #      Permanent prologue
        !           155:        emitlab("MAIN.")
        !           156: #
        !           157: #      The main loop.  We expect to read a series of statements.
        !           158:        while (nclause (1)) {
        !           159:                if (ident (cl_type, "procedure"))
        !           160:                        funct()
        !           161:                else if (ident (cl_type, "struct"))
        !           162:                        dostruct()
        !           163:                else
        !           164:                        dostmt()
        !           165:        }
        !           166: 
        !           167: 
        !           168: #      Epilogue
        !           169: exit:
        !           170:        emitg("END")
        !           171:        emitlab("START.")
        !           172:        emit("CODE('START.')")
        !           173:        for (i = 1, i <= deflist[0], i = i + 1) {
        !           174:                emiteos()
        !           175:                emit(deflist[i])
        !           176:        }
        !           177: 
        !           178:        # put out code to trap run-time errors
        !           179:        emiteos()
        !           180:        emit("&ERRLIMIT = 1")
        !           181:        emiteos()
        !           182:        emit("SETEXIT(.err.exit)")
        !           183: 
        !           184:        # put out code to assign the statement map
        !           185:        emiteos()
        !           186:        emit ("err.map = '")
        !           187:        while (bst_stab ? len(50) . bst_chunk = "") {
        !           188:                emit (bst_chunk && "'")
        !           189:                emiteos()
        !           190:                emitlab("+")
        !           191:                emit("'")
        !           192:        }
        !           193:        emit (bst_stab && "'")
        !           194: 
        !           195:        emitg("MAIN.")
        !           196:        emiteos()
        !           197: 
        !           198: #      Epilogue
        !           199:        input(.inf,-2,'/usr/lib/snocone/epilogue')
        !           200:        while (line = inf)
        !           201:                outf = line
        !           202:        endfile(-2)
        !           203: 
        !           204:        endfile(-1)
        !           205:        host (1, "chmod +x " && outfile)
        !           206: 
        !           207: 
        !           208: 
        !           209: #                      subroutines
        !           210: 
        !           211: 
        !           212: 
        !           213: 
        !           214: #      like span, but the pattern returned
        !           215: #      can also match the null string
        !           216: procedure nspan (str) {
        !           217:        return span (str) | ""
        !           218: }
        !           219: 
        !           220: #      a pattern that matches a list of zero or more
        !           221: #      "item"s separated by "delim"s
        !           222: procedure list (item, delim) {
        !           223:        return item && arbno (delim && item) | ""
        !           224: }
        !           225: 
        !           226: #      a pattern that matches the keyword given by the
        !           227: #      argument, insisting that it be followed by a non-letter.
        !           228: procedure kw (s) {
        !           229:        return span(letters) $ dummy &&
        !           230:                convert("ident(dummy,'" && s && "')", "EXPRESSION")
        !           231: }
        !           232: 
        !           233: #      return the name of the (new) top stack element
        !           234: procedure push() {
        !           235:        stackptr = stackptr + 1
        !           236:        nreturn  .stack[stackptr]
        !           237: }
        !           238: 
        !           239: #      return the value of the (old) top stack element
        !           240: procedure pop() {
        !           241:        pop = stack[stackptr]
        !           242:        stack[stackptr] = ""
        !           243:        stackptr = stackptr - 1
        !           244: }
        !           245: 
        !           246: #      return the name of the stack element n away from the top
        !           247: procedure peek (n) {
        !           248:        if (n >= stackptr)
        !           249:                go to err
        !           250:        nreturn .stack[stackptr - n]
        !           251: }
        !           252: 
        !           253: #      top()
        !           254: #      return the name of the top stack element
        !           255: procedure top() {
        !           256:        nreturn .stack[stackptr]
        !           257: }
        !           258: 
        !           259: #      isbin(x)
        !           260: #      is x a structure describing a binary operator?
        !           261: #      things like == and ||, which syntactically look
        !           262: #      more like functions than operators in their snobol form,
        !           263: #      are considered not to be operators.
        !           264: procedure isbin (x) {
        !           265:        if (differ (datatype (x), 'B') || differ (fn (op (x))))
        !           266:                freturn
        !           267: }
        !           268: 
        !           269: #      isneg(x)
        !           270: #      is x a structure describing a unary negation operator?
        !           271: procedure isneg (x) {
        !           272:        if (differ (datatype (x), 'U') || differ (op (x), '~'))
        !           273:                freturn
        !           274: }
        !           275: 
        !           276: #
        !           277: #      print an expression in snobol form
        !           278: procedure dprint (x) op, l, r, d, i, del {
        !           279:        d = datatype(x)
        !           280:        if (ident (d, 'STRING')) {
        !           281:                emit (x)
        !           282:                return
        !           283:        }
        !           284: 
        !           285:        if (ident (d, 'U')) {
        !           286:                # unary operator
        !           287:                emit (op (x))
        !           288:                if (isbin(r(x)))
        !           289:                        emit('(')
        !           290:                dprint(r(x))
        !           291:                if (isbin(r(x)))
        !           292:                        emit(')')
        !           293:                return
        !           294:        }
        !           295: 
        !           296: 
        !           297:        if (ident (d, 'FCALL')) {
        !           298:                # function call or array reference
        !           299:                emit (name (x))
        !           300:                emit (l (x))
        !           301:                r = args (x)
        !           302:                while (differ (r)) {
        !           303:                        emit (del)
        !           304:                        dprint (exp (r))
        !           305:                        del = ','
        !           306:                        r = next (r)
        !           307:                }
        !           308:                emit (r (x))
        !           309:                return
        !           310:        }
        !           311: 
        !           312:        if (ident (d, 'B')) {
        !           313:                # binary operator
        !           314:                op = op (x)
        !           315:                if (ident (op, or_binfo)) {
        !           316:                        emit ('(')
        !           317:                        bprint (x)
        !           318:                        emit (')')
        !           319:                        return
        !           320:                }
        !           321:                l = isbin(l(x)) && slp(op(l(x))) < srp(op) && 1 || ""
        !           322:                r = isbin(r(x)) && slp(op) > srp(op(r(x))) && 1 || ""
        !           323: 
        !           324:                # check for [f](a,b)
        !           325:                if (differ (fn (op))) {
        !           326:                        emit(out(op))
        !           327:                        emit('(')
        !           328:                        dprint(l(x))
        !           329:                        emit(',')
        !           330:                        dprint(r(x))
        !           331:                        emit(')')
        !           332:                        return
        !           333:                }
        !           334: 
        !           335:                # ordinary binary operator
        !           336:                if (differ (l))
        !           337:                        emit ('(')
        !           338:                dprint(l(x))
        !           339:                if (differ (l))
        !           340:                        emit (')')
        !           341:                emitb(out(op))
        !           342:                if (differ(r))
        !           343:                        emit('(')
        !           344:                dprint(r(x))
        !           345:                if (differ(r))
        !           346:                        emit(')')
        !           347:                return
        !           348:        }
        !           349: 
        !           350:        # unknown datatype -- this "shouldn't happen"
        !           351:        i = 1
        !           352:        emit(d)
        !           353:        emit ('(')
        !           354:        while (dprint (apply (field (d, i), x))) {
        !           355:                i = i + 1
        !           356:                emit (',')
        !           357:        }
        !           358:        emit (')')
        !           359: }
        !           360: 
        !           361: #      bprint(x)
        !           362: #      subroutine of dprint -- used to handle printing of
        !           363: #      things of the form (a,b), which are inherently
        !           364: #      associative and can therefore be grouped as follows
        !           365: #      ((a,b),c) <=>  (a,(b,c)) <=>  (a,b,c)
        !           366: procedure bprint (x) {
        !           367:        if (differ (datatype(x), 'B') || differ (op(x), or_binfo)) {
        !           368:                dprint (x)
        !           369:                return
        !           370:        }
        !           371:        bprint(l(x))
        !           372:        emit(',')
        !           373:        bprint(r(x))
        !           374: }
        !           375: 
        !           376: #      sprint(x)
        !           377: #      like dprint, but print in a form appropriate for
        !           378: #      an entire statement.  This procedure exists
        !           379: #      because if the top level operator is a concatenation,
        !           380: #      it is necessary to enclose the whole thing in parentheses.
        !           381: #      Otherwise it would be mistaken for a pattern match.
        !           382: procedure sprint (x) {
        !           383:        if (ident(datatype(x),'B') && ident(op(x),cat_binfo))
        !           384:                emit('(')
        !           385:        dprint(x)
        !           386:        if (ident(datatype(x),'B') && ident(op(x),cat_binfo))
        !           387:                emit(')')
        !           388:        emiteob()
        !           389: }
        !           390: 
        !           391: #      invoke(f)
        !           392: #      call an argument-free function in a context where
        !           393: #      a name is required, such as    arb . *invoke(.foo)
        !           394: procedure invoke (f) {
        !           395:        apply (f)
        !           396:        nreturn .dummy
        !           397: }
        !           398: 
        !           399: #      a unary operator has been detected during parsing
        !           400: procedure unop() r, op {
        !           401:        r = pop()
        !           402:        op = pop()
        !           403:        push() = u(op,r)
        !           404: }
        !           405: 
        !           406: #      mkfcall()
        !           407: #      Parsing has detected the beginning of a function call
        !           408: procedure mkfcall() {
        !           409:        push() = i_fcall()
        !           410:        nreturn .name(top())
        !           411: }
        !           412: 
        !           413: #      parsing has detected an argument to a function
        !           414: procedure mkarg() x, f {
        !           415:        x = argexp(pop(),"")
        !           416:        f = top()
        !           417:        if (differ(tail(f)))
        !           418:                next(tail(f)) = x
        !           419:        tail(f) = x
        !           420:        head(f) = ident(head(f)) && x
        !           421: }
        !           422: 
        !           423: #      parsing has detected the end of a function call
        !           424: procedure endfc() f {
        !           425:        f = pop()
        !           426:        push() = fcall(name(f),head(f),'(',')')
        !           427: }
        !           428: 
        !           429: #      the fcall at the head of the stack is really an array
        !           430: procedure mkarray() t {
        !           431:        t = top()
        !           432:        l(t) = '<'
        !           433:        r(t) = '>'
        !           434: }
        !           435: 
        !           436: #      the beginning of an expression has been detected
        !           437: procedure begexp() {
        !           438:        push() = bconv['(']
        !           439:        nreturn .dummy
        !           440: }
        !           441: 
        !           442: #      a binary operator has been detected.  We handle
        !           443: #      precedence here rather than in the grammar
        !           444: #      because it is less work.
        !           445: procedure binop() l, r, op, newr, newop {
        !           446:        while (lp(peek(3)) >= rp(peek(1))) {
        !           447:                newr = pop()
        !           448:                newop = pop()
        !           449:                r = pop()
        !           450:                op = pop()
        !           451:                l = pop()
        !           452:                push() = b(op,l,r)
        !           453:                push() = newop
        !           454:                push() = newr
        !           455:        }
        !           456: }
        !           457: 
        !           458: #      the end of an expression has been detected
        !           459: procedure endexp() l, r, op {
        !           460:        while (differ (peek (1), par_binfo)) {
        !           461:                r = pop()
        !           462:                op = pop()
        !           463:                l = pop()
        !           464:                push() = b(op,l,r)
        !           465:        }
        !           466:        r = pop()
        !           467:        pop()
        !           468:        push() = r
        !           469:        nreturn .dummy
        !           470: }
        !           471: 
        !           472: #      locate the binfo structure that describes the
        !           473: #      binary operator whose input character representation
        !           474: #      has been placed on the top of the stack.
        !           475: procedure mkbinfo() op {
        !           476:        op = bconv[pop()]
        !           477:        if (ident(op))
        !           478:                go to err
        !           479:        push() = op
        !           480: }
        !           481: 
        !           482: #      dotck()
        !           483: #      if necessary, append a leading zero to a floating-point
        !           484: #      constant that begins with a decimal point.  The idea
        !           485: #      that .5 is syntactically correct but semantically illegal
        !           486: #      is just too scary to leave in.
        !           487: procedure dotck() {
        !           488:        top() ? fence && '.' = '0.'
        !           489:        nreturn .dummy
        !           490: }
        !           491: 
        !           492: #      write label l to the output
        !           493: procedure emitlab (l) {
        !           494:        if (differ(l)) {
        !           495:                emiteos()
        !           496:                st_lab = l
        !           497:        }
        !           498:        nreturn .dummy
        !           499: }
        !           500: 
        !           501: #      put string s in the output
        !           502: procedure emit (s) {
        !           503:        if (differ(emit_eob))
        !           504:                emiteos()
        !           505:        st_body = st_body && s
        !           506: }
        !           507: 
        !           508: #      we are done with the body of the generated statement
        !           509: procedure emiteob() {
        !           510:        if (ident (emit_eob)) {
        !           511:                buildstab (emit_stno, gi_file, gi_line)
        !           512:                emit_eob = 1
        !           513:        }
        !           514: }
        !           515: 
        !           516: #      write success branch l
        !           517: procedure emits (l) {
        !           518:        emiteob()
        !           519:        st_s = l
        !           520: }
        !           521: 
        !           522: #      emitf(l)
        !           523: #      write failure branch l
        !           524: procedure emitf (l) {
        !           525:        emiteob()
        !           526:        st_f = l
        !           527: }
        !           528: 
        !           529: #      write unconditional branch l
        !           530: procedure emitg (l) {
        !           531:        emiteob()
        !           532:        st_s = ident(st_s) && l
        !           533:        st_f = ident(st_f) && l
        !           534: }
        !           535: 
        !           536: #      write s surrounded by blanks
        !           537: procedure emitb (s) {
        !           538:        emit(' ')
        !           539:        if (differ (s, ' ')) {
        !           540:                emit (s)
        !           541:                emit(' ')
        !           542:        }
        !           543: }
        !           544: 
        !           545: #      emiteos()out,goto
        !           546: #      we are done with the entire statement
        !           547: procedure emiteos() out, goto, s, del {
        !           548:        emit_eob = ""
        !           549:        if (differ(st_lab) || differ(st_body) || differ(st_s) || differ(st_f)) {
        !           550:                emit_stno = emit_stno + 1
        !           551:                out = st_lab && " " && st_body
        !           552:                if (differ (st_s) || differ (st_f)) {
        !           553:                        goto = " :"
        !           554:                        if (ident (st_s, st_f))
        !           555:                                goto = goto && "(" && st_s && ")"
        !           556:                        else {
        !           557:                                if (differ (st_s))
        !           558:                                        goto = goto && "S(" && st_s && ")"
        !           559:                                if (differ (st_f))
        !           560:                                        goto = goto && "F(" && st_f && ")"
        !           561:                        }
        !           562:                }
        !           563:                out = out && goto
        !           564:                while (size(out) >= 70) {
        !           565:                        out ? fence &&
        !           566:                                (arbno(break(" '" && '"') &&
        !           567:                                (" " | any("'" && '"') $ del &&
        !           568:                                break(*del) && len(1))) $ s &&
        !           569:                                *(size(s) > 50)) . outf = "+"
        !           570:                }
        !           571:                outf = out
        !           572:                st_lab = st_body = st_s = st_f = ""
        !           573:        }
        !           574: }
        !           575: 
        !           576: # attempt to read an input line, taking #include into account
        !           577: procedure getline() x, file, del, dir {
        !           578:        do {
        !           579:                # Try to read a line from the current file
        !           580:                while (x = gl_in) {
        !           581: 
        !           582:                        # We have a line: count it
        !           583:                        gl_line = gl_line + 1
        !           584: 
        !           585:                        # If it's not an include statement, we're done.
        !           586:                        if (~(x ? fence && "#" && *optblank && "include" &&
        !           587:                            *optblank && any('"<{' && "'") $ del &&
        !           588:                            break(*replace(del,'<{','>}')) . file &&
        !           589:                            len (1) && *optblank && rpos(0)))
        !           590:                                return x
        !           591: 
        !           592:                        # If the name is enclosed in quotes and
        !           593:                        # relative, then it is relative to the
        !           594:                        # directory containing the currently included
        !           595:                        # file, if any.  If it is enclosed in brackets,
        !           596:                        # it is relative to a canonical directory.
        !           597:                        if ("'" && '"' ? del) {
        !           598:                                if (substr (file, 1, 1) :!=: '/') {
        !           599:                                        if ((gl_file && '/') ? fence &&
        !           600:                                            (breakx('/') && len(1)) . dir &&
        !           601:                                            break('/') && len(1) && rpos(0))
        !           602:                                                file = dir && file
        !           603:                                }
        !           604:                        } else
        !           605:                                file = "/usr/lib/snocone/" && file
        !           606: 
        !           607:                        # If the name was enclosed by single quotes
        !           608:                        # or set brackets, ensure the particular file
        !           609:                        # was included only once.  Right now, we're pretty
        !           610:                        # literal-minded about when two files are really
        !           611:                        # the same:  'x' and './x' are different, for instance.
        !           612:                        if (('"<' ? del) || ident (inctab[file])) {
        !           613:                                inctab[file] = 1
        !           614:                                gl_open (file)
        !           615:                        }
        !           616:                }
        !           617: 
        !           618:                # We've reached the end of this file.
        !           619:                gl_close()
        !           620:        } while (gl_index >= 0 || gl_nextfile());
        !           621: 
        !           622:        freturn
        !           623: }
        !           624: 
        !           625: procedure gl_nextfile() {
        !           626:        gl_arg = gl_arg + 1
        !           627:        if (~gl_open (host (2, gl_arg)))
        !           628:                freturn
        !           629: }
        !           630: 
        !           631: procedure gl_close() {
        !           632:        endfile (gl_index)
        !           633:        gl_index = gl_index - 1
        !           634:        gl_file = gl_files[gl_index]
        !           635:        gl_line = gl_lines[gl_index]
        !           636:        if (gl_index >= 0)
        !           637:                input(.gl_in, gl_index)
        !           638:        gl_files[gl_index] = gl_lines[gl_index] = ""
        !           639: }
        !           640: 
        !           641: procedure gl_open (file) t {
        !           642:        gl_files[gl_index] = gl_file
        !           643:        gl_lines[gl_index] = gl_line
        !           644:        gl_index = gl_index + 1
        !           645:        gl_line = 0
        !           646:        gl_file = file
        !           647:        &errlimit = &errlimit + 1
        !           648:        t = setexit()
        !           649:        if (input (.gl_in, gl_index, file)) {
        !           650:                setexit(t)
        !           651:                &errlimit = &errlimit - 1
        !           652:                return
        !           653:        }
        !           654:        setexit(t)
        !           655:        gl_close()
        !           656:        error ("cannot read " && file)
        !           657:        freturn
        !           658: }
        !           659: 
        !           660: # Attempt to read an input line, return on ultimate failure.
        !           661: # This procedure strips comments and handles continuation lines.
        !           662: procedure getinput (recur) del, line {
        !           663: 
        !           664:        # have we already encountered the last EOF?
        !           665:        if (differ (gi_eof))
        !           666:                freturn
        !           667: 
        !           668:        if (line = line && getline()) {
        !           669: 
        !           670:                # if this is the first line, remember its identity
        !           671:                if (ident (recur)) {
        !           672:                        gi_file = gl_file
        !           673:                        gi_line = gl_line
        !           674:                }
        !           675: 
        !           676:                # strip comments
        !           677:                line ?
        !           678:                    fence &&
        !           679:                        (arbno (break ("'" && '"') &&
        !           680:                            len(1) $ del && break (*del) && len(1)) &&
        !           681:                        break ("'" && '"#')) . line && "#"
        !           682:                
        !           683:                # check for continuation
        !           684:                if (line? any("@$%^&*(-+=[<>|~,?:") && optblank && rpos(0))
        !           685:                        line = line && getinput(1)
        !           686: 
        !           687:                return line
        !           688:        }
        !           689: 
        !           690:        # we're out of input - signal final eof
        !           691:        gi_eof = 1
        !           692:        freturn
        !           693: }
        !           694: 
        !           695: #      phrase()
        !           696: #      return the next phrase from the input
        !           697: procedure phrase() del {
        !           698:        if (ph_buf ? fence && optblank && rpos(0)) {
        !           699:                if (ph_buf = phbuf && getinput())
        !           700:                        return phrase()
        !           701:                else
        !           702:                        freturn
        !           703:        }
        !           704: 
        !           705:        if (ph_buf ? fence && arbno(break('"' && "';") && fence &&
        !           706:            (any('"' && "'")$del && break(*del) && len(1) |
        !           707:            "")).phrase && ';'  = '')
        !           708:                return
        !           709:        phrase = ph_buf
        !           710:        ph_buf = ''
        !           711: }
        !           712: 
        !           713: #      return a new label
        !           714: procedure newlab() {
        !           715:        nl_count = nl_count + 1
        !           716:        return "L." && nl_count
        !           717: }
        !           718: 
        !           719: #      return a new label and place it on the current statement.
        !           720: #      If the current statement already has a label, use that.
        !           721: procedure marklab() {
        !           722:        if (differ (st_lab) && ident (emit_eob))
        !           723:                return st_lab
        !           724:        marklab = newlab()
        !           725:        emitlab (marklab)
        !           726: }
        !           727: 
        !           728: #      little routines to indicate what type of clause was read
        !           729: 
        !           730: #      expression clause
        !           731: procedure expcl() {
        !           732:        cl_type = "exp"
        !           733: }
        !           734: 
        !           735: #      goto clause
        !           736: procedure gocl() {
        !           737:        cl_type = "goto"
        !           738: }
        !           739: 
        !           740: #      read a new clause and classify it
        !           741: #      if end of input, error unless "okeof" argument is non-null,
        !           742: #      in which case we merely fail
        !           743: #      if rep_clause is set, give us the last clause again
        !           744: procedure nclause (okeof) del {
        !           745: nclause_start:
        !           746:        if (differ (rep_clause)) {
        !           747:                rep_clause = ""
        !           748:                if (ident (eof))
        !           749:                        return
        !           750:                else
        !           751:                        freturn
        !           752:        }
        !           753:        if (linebuf ? fence && *optblank && rpos(0)) {
        !           754:                if (linebuf = phrase())
        !           755:                        go to nclause_start
        !           756: 
        !           757:                #       end of input
        !           758:                if (ident(okeof)) {
        !           759:                        error ('premature EOF')
        !           760:                        go to exit
        !           761:                }
        !           762:                eof = 1
        !           763:                        freturn
        !           764:        }
        !           765: 
        !           766:        #       we really have some input
        !           767:        if (linebuf ? clause = del)
        !           768:                return
        !           769:        error("syntax error")
        !           770:        linebuf = ""
        !           771:        go to nclause_start
        !           772: }
        !           773: 
        !           774: procedure error (msg) prefix {
        !           775:        if (ident (gl_file))
        !           776:                prefix = "snocone"
        !           777:        else
        !           778:                prefix = gl_file && "(" && gl_line && ")"
        !           779:        terminal = prefix && ": " && msg
        !           780:        &code = 1
        !           781: }
        !           782: 
        !           783: #      handle a statement
        !           784: procedure dostmt() lab, lab2, e1, e2, e3, flip {
        !           785: 
        !           786:        if (ident(cl_type,"exp")) {
        !           787:                #       The clause is an expression,
        !           788:                #       so that's the whole statement
        !           789:                sprint(pop())
        !           790:                return
        !           791:        }
        !           792: 
        !           793:        #       It might be a sequence of statements in braces
        !           794:        if (ident(cl_type,"{")) {
        !           795:                nclause()
        !           796:                while (differ (cl_type, "}")) {
        !           797:                        dostmt()
        !           798:                        nclause()
        !           799:                }
        !           800:                return
        !           801:        }
        !           802: 
        !           803:        #       It might be a goto statement
        !           804:        if (ident (cl_type, "goto")) {
        !           805:                emitg (dest)
        !           806:                return
        !           807:        }
        !           808: 
        !           809:        #       It might be an if statement
        !           810:        if (ident(cl_type,"if")) {
        !           811:                e1 = pop()
        !           812: 
        !           813:                # optimize "if (~expr)"
        !           814:                if (isneg (e1)) {
        !           815:                        flip = 1
        !           816:                        e1 = r(e1)
        !           817:                }
        !           818: 
        !           819:                sprint(e1)
        !           820: 
        !           821:                #       Check for if(...)goto
        !           822:                nclause()
        !           823:                if (ident(cl_type,"goto")) {
        !           824:                        if (ident (flip))
        !           825:                                emits(dest)
        !           826:                        else
        !           827:                                emitf(dest)
        !           828: 
        !           829:                        #       In the case of if (e) goto l; else ...
        !           830:                        #       we can pretend the else wasn't there
        !           831:                        if (~nclause(1) || differ (cl_type, "else")) {
        !           832:                                rep_clause = 1
        !           833:                                emitlab (lab)
        !           834:                                return
        !           835:                        }
        !           836:                        nclause()
        !           837:                        dostmt()
        !           838:                        return
        !           839:                }
        !           840: 
        !           841:                #       Not if...goto, emit conditional jump over
        !           842:                #       the statement which follows.
        !           843:                lab = newlab()
        !           844:                if (ident (flip))
        !           845:                        emitf(lab)
        !           846:                else
        !           847:                        emits(lab)
        !           848:                dostmt()
        !           849: 
        !           850:                #       Check for else clause
        !           851:                if (nclause (1) && ident (cl_type, "else")) {
        !           852: 
        !           853:                        #       There is indeed an else clause
        !           854:                        lab2 = newlab()
        !           855:                        emitg(lab2)
        !           856:                        emitlab(lab)
        !           857:                        nclause()
        !           858:                        dostmt()
        !           859:                        emitlab(lab2)
        !           860:                        return
        !           861:                }
        !           862: 
        !           863:                #       No else clause; we must look at this clause again later
        !           864:                rep_clause = 1
        !           865:                emitlab(lab)
        !           866:                return
        !           867:        }
        !           868: 
        !           869:        #       Check for a while clause
        !           870:        if (ident(cl_type,"while")) {
        !           871:                lab = marklab()
        !           872: 
        !           873:                # optimize "while(~exp)"
        !           874:                e1 = pop()
        !           875:                if (isneg (e1)) {
        !           876:                        flip = 1
        !           877:                        e1 = r(e1)
        !           878:                }
        !           879: 
        !           880:                sprint(e1)
        !           881:                lab2 = newlab()
        !           882:                if (ident (flip))
        !           883:                        emitf(lab2)
        !           884:                else
        !           885:                        emits(lab2)
        !           886:                nclause()
        !           887:                dostmt()
        !           888:                emitg(lab)
        !           889:                emitlab(lab2)
        !           890:                return
        !           891:        }
        !           892: 
        !           893:        #       Check for a do clause
        !           894:        if (ident(cl_type,"do")) {
        !           895:                lab = marklab()
        !           896:                nclause()
        !           897:                dostmt()
        !           898:                nclause()
        !           899:                if (differ(cl_type,"while")) {
        !           900:                        error ("expected 'while', found " && cl_type)
        !           901:                        rep_clause = 1
        !           902:                        return
        !           903:                }
        !           904:                e1 = pop()
        !           905:                if (isneg (e1)) {
        !           906:                        flip = 1
        !           907:                        e1 = r (e1)
        !           908:                }
        !           909:                sprint(e1)
        !           910:                if (ident (flip))
        !           911:                        emits (lab)
        !           912:                else
        !           913:                        emitf (lab)
        !           914:                return
        !           915:        }
        !           916: 
        !           917:        #       Check for a "for" clause
        !           918:        if (ident(cl_type,"for")) {
        !           919:                e3 = pop()
        !           920:                e2 = pop()
        !           921:                e1 = pop()
        !           922:                sprint(e1)
        !           923:                emiteob()
        !           924:                lab = marklab()
        !           925:                lab2 = newlab()
        !           926:                if (isneg (e2)) {
        !           927:                        flip = 1
        !           928:                        e2 = r (e2)
        !           929:                }
        !           930:                sprint(e2)
        !           931:                if (ident (flip))
        !           932:                        emitf (lab2)
        !           933:                else
        !           934:                        emits (lab2)
        !           935:                nclause()
        !           936:                dostmt()
        !           937:                sprint(e3)
        !           938:                emitg(lab)
        !           939:                emitlab(lab2)
        !           940:                return
        !           941:        }
        !           942: 
        !           943:        #       could be some kind of return statement
        !           944:        if (cl_type ? "return") {
        !           945:                e1 = pop()
        !           946:                if (differ(e1)) {
        !           947:                        if (differ(fname))
        !           948:                                e1 = b(bconv["="],fname,e1)
        !           949:                        sprint(e1)
        !           950:                }
        !           951:                emitg (replace(cl_type,
        !           952:                        "abcdefghijklmnopqrstuvwxyz",
        !           953:                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
        !           954:                return
        !           955:        }
        !           956: 
        !           957:        #       could even be a null statement
        !           958:        if (ident(cl_type))
        !           959:                return
        !           960: 
        !           961:        error("bad " && cl_type && " clause, ignored")
        !           962: }
        !           963: 
        !           964: #      We have seen "struct" -- parse the 'declaration'
        !           965: procedure dostruct() args {
        !           966:        if (expect ('{')) {
        !           967:                args = getlist ('}')
        !           968:                deflist[deflist[0] = deflist[0] + 1] =
        !           969:                        "DATA('" && stname && "(" && args && ")')"
        !           970:        } else
        !           971:                error ("bad structure definition")
        !           972:        expect ('}')
        !           973: }
        !           974: 
        !           975: #      We have seen "procedure" -- we must now parse the header
        !           976: procedure funct() args, locals, flabel {
        !           977:        if (expect('(')) {
        !           978:                if (~(args = getlist(')')))
        !           979:                        go to fu_error
        !           980:                expect(')')
        !           981:                if (~(locals = getlist('{')))
        !           982:                        go to fu_error
        !           983:        }
        !           984: 
        !           985:        deflist[deflist[0] = deflist[0] + 1] =
        !           986:                "DEFINE('" && fname && '(' && args && ')' && locals && "')"
        !           987: 
        !           988:        #       if we just emitted the end of a previous procedure,
        !           989:        #       we can jump around this one in one go
        !           990:        if (ident (emit_eob) && st_lab ? ".END") {
        !           991:                flabel = st_lab
        !           992:                st_lab = ""
        !           993:                emitlab(fname)
        !           994:                nclause()
        !           995:                dostmt()
        !           996:                emitg("RETURN")
        !           997:                emitlab(flabel)
        !           998:                return
        !           999:        }
        !          1000: 
        !          1001:        emitg(fname && '.END')
        !          1002:        emitlab(fname)
        !          1003:        nclause()
        !          1004:        dostmt()
        !          1005:        emitg("RETURN")
        !          1006:        emitlab(fname && '.END')
        !          1007:        return
        !          1008: 
        !          1009: fu_error:
        !          1010:        error("bad function definition")
        !          1011: }
        !          1012: 
        !          1013: #      the input should now contain something matching "p"
        !          1014: #      possibly surrounded by white space.  If not, fail
        !          1015: procedure expect (p) {
        !          1016: 
        !          1017:        # throw away blank lines
        !          1018:        while (linebuf ? fence && optblank && rpos (0)) {
        !          1019:                if (~(linebuf = phrase()))
        !          1020:                        freturn
        !          1021:        }
        !          1022: 
        !          1023:        # try to match the given pattern, possibly preceded by white space
        !          1024:        if (linebuf ? fence && optblank && *p = "")
        !          1025:                return
        !          1026: 
        !          1027:        # didn't match: fail
        !          1028:        freturn
        !          1029: }
        !          1030: 
        !          1031: #      expect an identifier in the input; return it.
        !          1032: procedure getid() {
        !          1033:        if (expect (*identifier . getid))
        !          1034:                return
        !          1035:        freturn
        !          1036: }
        !          1037: 
        !          1038: #      expect a list of identifiers followed by tail
        !          1039: procedure getlist (tail) del {
        !          1040: getlist_start:
        !          1041:        if (expect(tail)) {
        !          1042:                linebuf = tail && linebuf
        !          1043:                return
        !          1044:        }
        !          1045:        if (getlist = getlist && del && getid()) {
        !          1046:                expect(',')
        !          1047:                del = ','
        !          1048:                go to getlist_start
        !          1049:        }
        !          1050:        if (expect(tail))
        !          1051:                return
        !          1052:        freturn
        !          1053: }
        !          1054: 
        !          1055: # This procedure is called once for each output statement.
        !          1056: # It maintains the correspondence between Snocone and SNOBOL4
        !          1057: # statements, which is inserted into the output for debugging.
        !          1058: procedure buildstab (stmt, file, line) desc, pad {
        !          1059:        pad = dupl ("?", stmt - bst_stmt - 1)
        !          1060:        bst_stab = bst_stab && pad
        !          1061:        if (ident (file, bst_file)) {
        !          1062:                if (differ(pad) || line != bst_line + 1)
        !          1063:                        desc = line
        !          1064:        } else
        !          1065:                desc = file && ":" && line
        !          1066:        bst_stab = bst_stab && desc && ","
        !          1067:        bst_stmt = stmt
        !          1068:        bst_file = file
        !          1069:        bst_line = line
        !          1070: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.